microsoft/aspire · error · ArgumentException

The apiPath must start with '/'.

Error message

The apiPath must start with '/'.

What it means

The apiPath for the API proxy must be an absolute route beginning with '/'. Aspire normalizes the path (trimming trailing slashes) and mounts it in the dev-server proxy, which relies on the leading slash; a relative value like "api" would produce an invalid or unintended route.

Solutions

  1. Prefix the value with '/' before passing it, e.g. apiPath: "/api".
  2. Normalize at the call site: if (!path.StartsWith('/')) path = "/" + path.
  3. Validate/normalize configurable path values when loading settings.

Example fix

// before
.WithApiProxy(apiPath: "api", apiTarget: apiBuilder);
// after
.WithApiProxy(apiPath: "/api", apiTarget: apiBuilder);
Defensive patterns

Strategy: validation

Validate before calling

if (apiPath is not null && !apiPath.StartsWith('/'))
    apiPath = "/" + apiPath;

Type guard

bool IsAbsoluteRoutePath(string? p) => p is not null && p.StartsWith('/');

Prevention

When it happens

Trigger: Calling the API-proxy extension with apiPath: "api" (no leading slash), often a value read from configuration or built by string concatenation.

Common situations: Paths loaded from appsettings/environment variables that lack the leading slash; concatenation like $"{basePath}/api" where basePath is empty; users used to relative route registration APIs.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/ddac79f995ce96d0. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.JavaScript/JavaScriptHostingExtensions.cs:1303

    {
        ArgumentNullException.ThrowIfNull(builder);
        ArgumentException.ThrowIfNullOrEmpty(options.OutputPath);

        if (apiPath is not null && apiTarget is null)
        {
            throw new ArgumentException("apiTarget is required when apiPath is specified.", nameof(apiTarget));
        }

        if (apiTarget is not null && apiPath is null)
        {
            throw new ArgumentException("apiPath is required when apiTarget is specified.", nameof(apiPath));
        }

        if (apiPath is not null && apiTarget is not null)
        {
            if (!apiPath.StartsWith('/'))
            {
                throw new ArgumentException("The apiPath must start with '/'.", nameof(apiPath));
            }

            apiPath = apiPath.TrimEnd('/');

            if (apiPath.Length == 0)
            {
                throw new ArgumentException("The apiPath must not be '/' — it would match all requests and make the static site unreachable.", nameof(apiPath));
            }

            ValidateApiPath(apiPath);
            builder.WithReference(apiTarget);
        }

        if (!builder.ApplicationBuilder.ExecutionContext.IsPublishMode)
        {
            return builder;
        }

View on GitHub (pinned to 25830f84bd)