HangfireIO/Hangfire · critical · InvalidOperationException

Current OWIN environment does not contain an instance of the

Error message

Current OWIN environment does not contain an instance of the `CancellationToken` class neither under `host.OnAppDisposing`, nor `server.OnDispose` key.
Please use another OWIN host or create an instance of the `BackgroundJobServer` class manually.

What it means

When starting a BackgroundJobServer via the OWIN AppBuilderExtensions pipeline, Hangfire looks for a cancellation token under the OWIN keys 'host.OnAppDisposing' or 'server.OnDispose' so it can shut the server down cleanly when the host stops. If neither key yields a CancellationToken, an InvalidOperationException is thrown because Hangfire cannot register its shutdown callback. The exception explicitly tells you to use a different OWIN host or to instantiate BackgroundJobServer manually.

Source

Thrown at src/Hangfire.Core/AppBuilderExtensions.cs:333

            [NotNull] this IAppBuilder builder,
            [NotNull] IBackgroundProcessingServer server)
        {
            if (builder == null) throw new ArgumentNullException(nameof(builder));
            if (server == null) throw new ArgumentNullException(nameof(server));

            Servers.TryAdd(server, null);

            var context = new OwinContext(builder.Properties);
            var token = context.Get<CancellationToken>("host.OnAppDisposing");
            if (token == default(CancellationToken))
            {
                // https://github.com/owin/owin/issues/27
                token = context.Get<CancellationToken>("server.OnDispose");
            }

            if (token == default(CancellationToken))
            {
                throw new InvalidOperationException(
                    "Current OWIN environment does not contain an instance of the `CancellationToken` class neither under `host.OnAppDisposing`, nor `server.OnDispose` key.\r\n"
                    + "Please use another OWIN host or create an instance of the `BackgroundJobServer` class manually.");
            }

            token.Register(OnAppDisposing, server);
            return builder;
        }

        private static void OnAppDisposing(object state)
        {
            var logger = LogProvider.GetLogger(typeof(AppBuilderExtensions));
            logger.Info("Web application is shutting down via OWIN's host.OnAppDisposing callback.");

            ((IDisposable) state).Dispose();

            if (state is IBackgroundProcessingServer server)
                Servers.TryRemove(server, out _);
        }

View on GitHub (pinned to c236dd0f93)

Solutions

  1. Switch to a host that provides the shutdown token — Microsoft.Owin.Host.SystemWeb (IIS) or Microsoft.Owin.Host.HttpListener both populate host.OnAppDisposing.
  2. If you control the OWIN environment dictionary, add 'host.OnAppDisposing' (a CancellationToken) to builder.Properties before calling UseHangfireServer.
  3. Bypass the OWIN extension and create BackgroundJobServer manually with your own CancellationToken/WebHost stop hook.
  4. For ASP.NET Core apps, use services.AddHangfireServer() instead of the OWIN pipeline.

Example fix

// before
app.UseHangfireServer(); // throws under minimal OWIN host

// after (manual server with own token)
var server = new BackgroundJobServer();
// dispose 'server' on application shutdown

// or for ASP.NET Core
services.AddHangfire(config => config.UseXXXStorage());
services.AddHangfireServer();
Defensive patterns

Strategy: fallback

Validate before calling

var ctx = new OwinContext(builder.Properties);
bool hasShutdownToken =
    ctx.Get<CancellationToken>("host.OnAppDisposing") != default ||
    ctx.Get<CancellationToken>("server.OnDispose") != default;
if (!hasShutdownToken)
{
    // host does not support shutdown token; do not call UseHangfireServer
}

Type guard

static bool OwinHostSupportsShutdown(IAppBuilder b)
{
    var ctx = new OwinContext(b.Properties);
    return ctx.Get<CancellationToken>("host.OnAppDisposing") != default(CancellationToken)
        || ctx.Get<CancellationToken>("server.OnDispose") != default(CancellationToken);
}

Try / catch

try { app.UseHangfireServer(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("host.OnAppDisposing"))
{
    // fall back to a manually created BackgroundJobServer
}

Prevention

When it happens

Trigger: Calling appBuilder.UseHangfireServer(...) under an OWIN host that does not populate 'host.OnAppDisposing' or 'server.OnDispose' in its environment dictionary — e.g., a minimal/custom OWIN host, an in-memory test host, or certain non-Microsoft hosts.

Common situations: Using a third-party or self-built OWIN host that omits shutdown-token registration; running Hangfire OWIN integration inside a test harness (OwinTestServer / Microsoft.Owin.Testing) that does not expose a shutdown token; upgrading an OWIN host that dropped the legacy key.

Related errors


AI-assisted analysis of HangfireIO/Hangfire@c236dd0f93 (2026-08-13). Data as JSON: /api/errors/4efd439c4edc0fe0. Report an issue: GitHub.