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

WriteFileHttpResponse writes its response to the live ASP.NET HTTP context of the request that started the workflow. If IHttpContextAccessor.HttpContext is null at execution time, the activity throws a FaultException with code NoHttpContext, because there is no response stream to write to. This happens when the workflow was suspended after the HTTP request ended and later resumed outside the original request context.

Solutions

  1. Do not use WriteHttpResponse/WriteFileHttpResponse after a suspension point; instead complete the HTTP request early (e.g., 202 Accepted) and deliver results via another channel (webhook callback, SignalR, storage link).
  2. Restructure the workflow so the HTTP response is written before any blocking/bookmark activity.
  3. If HTTP-correlated resume is required, ensure the resuming request itself carries the HTTP context (i.e., resume via an HttpEndpoint activity) rather than a non-HTTP trigger.

Example fix

// before: HTTP trigger -> Delay/Task -> WriteFileHttpResponse (fails on resume)
// after: HTTP trigger -> WriteHttpResponse("accepted") -> Delay/Task -> deliver file via callback/storage
Defensive patterns

Strategy: validation

Validate before calling

// Before the WriteFileHttpResponse activity runs, assert an HTTP context exists
var httpContext = httpContextAccessor.HttpContext;
if (httpContext is null || !httpContext.Response.HasStarted ^ true)
{
    // take an alternate delivery path (202 + callback) instead of writing an HTTP file response
}

Try / catch

// Handle at workflow fault level
context.Faulted += (args) => {
    if (args.Fault.Code == HttpFaultCodes.NoHttpContext)
        logger.LogWarning("Workflow tried to write an HTTP response without a live request; use callback delivery instead");
};

Prevention

When it happens

Trigger: ExecuteAsync of WriteFileHttpResponse runs while httpContextAccessor.HttpContext is null — the workflow resumed from a bookmark on a background thread, in a virtual actor scheduler, after a server restart, or on a different node, so the original HTTP request/response pair no longer exists.

Common situations: A workflow blocks (e.g., waits for user task or timer) after an HttpEndpoint trigger and then attempts to write an HTTP file response upon resume; load-balanced deployments where the resume happens on another instance; long-running workflows outliving the HTTP request timeout.

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/2eea72923aefdb4f. Report an issue: GitHub.

Appendix: source

Thrown at src/modules/Elsa.Http/Activities/WriteFileHttpResponse.cs:74

    /// </summary>
    [Input(Description = "Whether to enable resumable downloads. When enabled, the client can resume a download if the connection is lost.")]
    public Input<bool> EnableResumableDownloads { get; set; } = null!;

    /// <summary>
    /// The correlation ID of the download. Used to resume a download.
    /// </summary>
    [Input(Description = "The correlation ID of the download used to resume a download. If left empty, the x-download-id header will be used.")]
    public Input<string> DownloadCorrelationId { get; set; } = null!;

    /// <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);
    }

    private async Task WriteResponseAsync(ActivityExecutionContext context, HttpContext httpContext)
    {
        // Get content and content type.
        var content = context.Get(Content);

        // Write content.
        var downloadables = GetDownloadables(context, httpContext, content).ToList();
        await SendDownloadablesAsync(context, httpContext, downloadables);

View on GitHub (pinned to fe9217bdfa)