elsa-workflows/elsa-core · critical · Exception

There was no base URL configured, which means no absolute…

Error message

There was no base URL configured, which means no absolute URL can be generated from outside the context of an HTTP request. Please make sure that `HttpActivityOptions` is configured correctly. The configuration key used in most Elsa samples is usually: "Elsa:Server:BaseUrl"

What it means

DefaultAbsoluteUrlProvider.ToAbsoluteUrl builds absolute URLs for HTTP callbacks and webhook responses. It requires HttpActivityOptions.BaseUrl to be configured; when running outside an active HTTP request there is no ambient request to infer a base from, so it throws when BaseUrl is null.

Solutions

  1. Configure the base URL: services.Configure<HttpActivityOptions>(o => o.BaseUrl = new Uri("https://myhost/")) or add "Elsa": { "Server": { "BaseUrl": "https://myhost" } } to configuration
  2. Verify the environment actually provides the config key (env var Elsa__Server__BaseUrl in containers)
  3. In tests, set HttpActivityOptions.BaseUrl explicitly (e.g. http://localhost) in the test fixture
  4. Wrap callback-URL generation behind a check so it only runs when a base URL is configured

Example fix

// before
services.AddHttpActivities(); // no BaseUrl configured
// after
services.AddHttpActivities(http => http.BaseUrl = new Uri(configuration["Elsa:Server:BaseUrl"]!));
Defensive patterns

Strategy: validation

Validate before calling

var baseUrl = httpClientFactory /* or config */ ...;
if (Uri.TryCreate(config["Elsa:Server:BaseUrl"], UriKind.Absolute, out var uri))
    services.Configure<HttpActivityOptions>(o => o.BaseUrl = uri);
else
    throw new InvalidOperationException("HttpActivityOptions.BaseUrl is not configured");

Try / catch

try { url = absoluteUrlProvider.ToAbsoluteUrl(path); }
catch (Exception ex) when (ex.Message.Contains("no base URL configured"))
{
    logger.LogError(ex, "HttpActivityOptions.BaseUrl is missing; configure Elsa:Server:BaseUrl");
    throw;
}

Prevention

When it happens

Trigger: Calling ToAbsoluteUrl(relativePath) (directly or via HttpEndpoint signal/callback URL generation) while HttpActivityOptions.BaseUrl was never set in DI configuration, e.g. missing the Elsa:Server:BaseUrl config key.

Common situations: Self-hosted console apps or background/workflow-server hosts that never call UseBaseUrl; missing appsettings.json section in a deployed environment; Docker/K8s image deployed without the Server:BaseUrl environment variable.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at src/modules/Elsa.Http/Services/DefaultAbsoluteUrlProvider.cs:22

namespace Elsa.Http.Services;

/// <inheritdoc />
public class DefaultAbsoluteUrlProvider : IAbsoluteUrlProvider
{
    private readonly IOptions<HttpActivityOptions> _options;
    
    /// <summary>
    /// Initializes a new instance of the <see cref="DefaultAbsoluteUrlProvider"/> class.
    /// </summary>
    public DefaultAbsoluteUrlProvider(IOptions<HttpActivityOptions> options) => _options = options;

    /// <inheritdoc />
    public Uri ToAbsoluteUrl(string relativePath)
    {
        var baseUrl = _options.Value.BaseUrl;

        if (baseUrl == null)
            throw new Exception(
                "There was no base URL configured, which means no absolute URL can be generated from outside the context of an HTTP request. Please make sure that `HttpActivityOptions` is configured correctly. The configuration key used in most Elsa samples is usually: \"Elsa:Server:BaseUrl\"");

        // To not lose any base path information, we need to ensure that:
        // - Base path ends with a slash.
        // - Relative path does NOT start with a slash.
        var baseUri = new Uri(baseUrl.ToString().TrimEnd('/') + '/');
        relativePath = relativePath.TrimStart('/');

        return new Uri(baseUri, relativePath);
    }
}

View on GitHub (pinned to fe9217bdfa)