/// <summary>
            /// Try to invoke the specified <paramref name="action"/> and handle any exception that occurs.
            /// If an exception occurs and <paramref name="shouldMitigate"/> is true, the specified <paramref name="mitigator"/> is used to apply a mitigation.
            /// </summary>
            /// <param name="action">The action to try.</param>
            /// <param name="entity">The entity being loaded/mitigated.</param>
            /// <param name="shouldMitigate">true if errors should be mitigated; otherwise, false.</param>
            /// <param name="mitigator">The mitigator to use if the failed action should be mitigated.</param>
            private void TryMitigate(Action action, ReactiveEntity entity, bool shouldMitigate, ReactiveEntityRecoveryFailureMitigator mitigator)
            {
                try
                {
                    action();
                }
                catch (Exception ex)
                {
                    var error = new EntityLoadFailedException(entity.Uri, entity.Kind, ex);

                    if (shouldMitigate && Parent._engine.OnEntityLoadFailed(entity.Uri, entity, entity.Kind, error, out ReactiveEntityRecoveryFailureMitigation mitigation))
                    {
                        var trace = Parent.TraceSource;

                        trace.Mitigation_Execute(entity.Uri, mitigation);

#pragma warning disable IDE0079 // Remove unnecessary suppression.
#pragma warning disable CA1031  // Do not catch general exception types. (Protecting against engine unavailability; last resort mitigation with tracing of errors.)

                        try
                        {
                            if (!mitigator.DoMitigate(entity, mitigation))
                            {
                                trace.Mitigation_NotAccepted(mitigation, entity.Uri, ex);
                            }
                        }
                        catch (Exception mx)
                        {
                            trace.Mitigation_Failure(mitigation, entity.Uri, mx);
                        }

#pragma warning restore CA1031
#pragma warning restore IDE0079

                        // For this implementation, whenever a mitigation occurs, we will throw a
                        // bail out exception. This is to prevent further processing of the
                        // 'normal' recovery process from throwing additional errors that will
                        // trigger additional mitigations. An unfortunate consequence is that the
                        // mitigations must ensure all steps that would have occurred in the
                        // 'normal' recovery process occur in the mitigation (esp. for things
                        // mitigations like `Regenerate`. Right now, this is not a problem, as the
                        // steps being mitigated are late in the recovery process.
                        throw new MitigationBailOutException();
                    }

                    // This may result in a second call to the `EntityLoadFailed` event.
                    throw;
                }
            }
                private void HandleError(ReactiveEntityKind kind, string key, IReactiveResource entity, Exception ex, Action <Exception> unhandled)
                {
                    if (ex is EngineUnloadedException)
                    {
                        return;
                    }

                    var uri = new Uri(key);

                    var error = new EntityLoadFailedException(uri, kind, ex);

                    // TODO: support mitigation for any kind of artifact
                    if (!_engine.OnEntityLoadFailed(uri, entity, kind, error, out _))
                    {
                        unhandled(error);
                    }
                }