elsa-workflows/elsa-core · error · FaultException

NoHttpContext

NoHttpContext

Error message

The HTTP context was lost during workflow execution. This typically occurs when a workflow initiated from an HTTP endpoint is suspended and later resumed in a different execution context (e.g., background processing, virtual actor, or after a workflow transition). The original HTTP request context that expects a response is no longer available.

What it means

WriteHttpResponse writes a response body/status to the ASP.NET HTTP context captured when the workflow's HTTP endpoint received the request. If IHttpContextAccessor.HttpContext is null during ExecuteAsync, the activity throws a FaultException with code NoHttpContext, because there is no live response to write. This guards against workflows resuming after suspension in a non-HTTP execution context.

Solutions

  1. Write the HTTP response before any suspending activity; if asynchronous delivery is needed, respond with 202 Accepted early and push the final result via a callback/SignalR.
  2. Refactor so the final response is produced by a subsequent HttpEndpoint request (the client polls or a webhook triggers the completion response).
  3. Use workflow-correlated delivery mechanisms (e.g., HTTP bookmarks where the resume request itself carries the HTTP context) instead of assuming the original context survives.

Example fix

// before: HttpEndpoint -> Event(approval) -> WriteHttpResponse("done") // NoHttpContext on resume
// after: HttpEndpoint -> WriteHttpResponse("pending") -> Event(approval) -> notify via webhook/SignalR
Defensive patterns

Strategy: validation

Validate before calling

// Guard before writing the response in the workflow
var hasHttpContext = httpContextAccessor.HttpContext is not null;
if (!hasHttpContext)
{
    // fall back to non-HTTP delivery (store result, notify via SignalR/webhook)
}

Try / catch

// Inspect the fault after resume
workflowDispatcher.OnFault((instance, fault) => {
    if (fault.Code == HttpFaultCodes.NoHttpContext)
        logger.LogWarning("Workflow {Id} attempted HTTP response without context; switch to callback pattern", instance.Id);
});

Prevention

When it happens

Trigger: ExecuteAsync of WriteHttpResponse runs while httpContextAccessor.HttpContext is null — the workflow was suspended (bookmark, timer, task) after the HTTP request completed and resumed on a background worker, virtual actor, or different node without the original request context.

Common situations: HTTP-triggered workflow with an intermediate Delay or human-task approval, then attempting to send the final HTTP response; server restarts while the workflow was suspended; distributed deployments where the resuming instance never saw the original request.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13). Data as JSON: /api/errors/09d99d3cb162d72a. Report an issue: GitHub.

Appendix: source

Thrown at src/modules/Elsa.Http/Activities/WriteHttpResponse.cs:85

    /// <summary>
    /// The headers to return along with the response.
    /// </summary>
    [Input(
        Description = "The headers to send along with the response.",
        UIHint = InputUIHints.JsonEditor,
        Category = "Advanced"
    )]
    public Input<HttpHeaders?> ResponseHeaders { get; set; } = new(new HttpHeaders());

    /// <inheritdoc />
    protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
    {
        var httpContextAccessor = context.GetRequiredService<IHttpContextAccessor>();
        var httpContext = httpContextAccessor.HttpContext;

        if (httpContext == null)
        {
            throw new FaultException(
                HttpFaultCodes.NoHttpContext, 
                HttpFaultCategories.Http, 
                DefaultFaultTypes.System, 
                "The HTTP context was lost during workflow execution. This typically occurs when a workflow initiated from an HTTP endpoint is suspended and later resumed in a different execution context (e.g., background processing, virtual actor, or after a workflow transition). The original HTTP request context that expects a response is no longer available.");
        }

        await WriteResponseAsync(context, httpContext.Response);
    }

    private async Task WriteResponseAsync(ActivityExecutionContext context, HttpResponse response)
    {
        // Set status code.
        var statusCode = StatusCode.GetOrDefault(context, () => HttpStatusCode.OK);
        response.StatusCode = (int)statusCode;

        // Add headers.
        var headers = context.GetHeaders(ResponseHeaders);
        foreach (var header in headers)

View on GitHub (pinned to fe9217bdfa)