dotnet/aspnetcore · error · Error

No url defined.

Error message

No url defined.

What it means

FetchHttpClient.send throws if the HttpRequest has no url. Without a destination, fetch() cannot proceed, so the client fails fast rather than emitting a cryptic fetch error.

Solutions

  1. Pass a fully-qualified, non-empty URL string to withUrl().
  2. Validate the URL is truthy before constructing the connection: if (!hubUrl) throw new Error("hubUrl missing").
  3. Check that any environment variable feeding the URL is set at runtime.

Example fix

// before
const url = process.env.HUB_URL;
const conn = new signalR.HubConnectionBuilder().withUrl(url).build();

// after
const url = process.env.HUB_URL;
if (!url) throw new Error("HUB_URL not set");
const conn = new signalR.HubConnectionBuilder().withUrl(url).build();
Defensive patterns

Strategy: validation

Validate before calling

if (!url) throw new Error("withUrl requires a non-empty URL");
new URL(url); // throws on malformed URLs too
new signalR.HubConnectionBuilder().withUrl(url).build();

Type guard

function isNonEmptyUrl(u: unknown): u is string {
  return typeof u === "string" && u.length > 0 && /^https?:\/\//.test(u);
}

Try / catch

try { await connection.start(); }
catch (e) {
  if (e instanceof Error && e.message === "No url defined.") {
    throw new Error("Configuration error: hub URL was empty.");
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling httpClient.send with a request object whose url is empty/undefined. Typically a result of building a request from an empty withUrl configuration, or a templated URL that resolved to undefined.

Common situations: HubConnectionBuilder().withUrl("") or withUrl(undefined) where the URL was supposed to come from config/env. URL template that didn't interpolate. Manually invoking httpClient.send for a custom call and forgetting the url.

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/152018cb828a2e8e. Report an issue: GitHub.

Appendix: source

Thrown at src/SignalR/clients/ts/signalr/src/FetchHttpClient.ts:69

            // Node needs EventListener methods on AbortController which our custom polyfill doesn't provide
            this._abortControllerType = requireFunc("abort-controller");
        } else {
            this._abortControllerType = AbortController;
        }
    }

    /** @inheritDoc */
    public async send(request: HttpRequest): Promise<HttpResponse> {
        // Check that abort was not signaled before calling send
        if (request.abortSignal && request.abortSignal.aborted) {
            throw new AbortError();
        }

        if (!request.method) {
            throw new Error("No method defined.");
        }
        if (!request.url) {
            throw new Error("No url defined.");
        }

        const abortController = new this._abortControllerType();

        let error: any;
        // Hook our abortSignal into the abort controller
        if (request.abortSignal) {
            request.abortSignal.onabort = () => {
                abortController.abort();
                error = new AbortError();
            };
        }

        // If a timeout has been passed in, setup a timeout to call abort
        // Type needs to be any to fit window.setTimeout and NodeJS.setTimeout
        let timeoutId: any = null;
        if (request.timeout) {
            const msTimeout = request.timeout!;

View on GitHub (pinned to 3600ca084e)