dotnet/aspnetcore · error · Error

'EventSource' is not supported in your environment.

Error message

'EventSource' is not supported in your environment.

What it means

_constructTransport throws if ServerSentEvents was selected but options.EventSource is falsy. EventSource is resolved from the global EventSource (browser) or the 'eventsource' npm module under Node; if neither is present, SSE cannot be used.

Solutions

  1. Install 'eventsource' (npm install eventsource) when running on Node.
  2. Provide an EventSource implementation explicitly: withUrl(url, { EventSource: MyESImpl }).
  3. Switch to LongPolling or WebSockets, which may be available in your environment.
  4. Confirm the bundler is not stripping the EventSource polyfill/global.

Example fix

// before: Node without 'eventsource'
const conn = new signalR.HubConnectionBuilder()
  .withUrl(url, { transport: signalR.HttpTransportType.ServerSentEvents })
  .build();

// after: supply an implementation
import EventSource from "eventsource";
const conn = new signalR.HubConnectionBuilder()
  .withUrl(url, { transport: signalR.HttpTransportType.ServerSentEvents, EventSource })
  .build();
Defensive patterns

Strategy: validation

Validate before calling

function resolveEventSource(): typeof EventSource | undefined {
  if (typeof EventSource !== "undefined") return EventSource;
  try { return require("eventsource"); } catch { return undefined; }
}

Type guard

function hasEventSourceImpl(opts: signalR.IHttpConnectionOptions): boolean {
  return typeof opts.EventSource === "function" || typeof EventSource !== "undefined";
}

Try / catch

try { await connection.start(); }
catch (e) {
  if (e instanceof Error && /'EventSource' is not supported/.test(e.message)) {
    opts.EventSource = require("eventsource");
    return newConnection(opts);
  }
  throw e;
}

Prevention

When it happens

Trigger: Transport selection picks HttpTransportType.ServerSentEvents but options.EventSource is undefined. The constructor only assigns EventSource when the global exists or, under Platform.isNode, require('eventsource') succeeded.

Common situations: Running in Node without the 'eventsource' package installed. Running in a non-browser environment without an EventSource polyfill. Bundler removed the dynamic require('eventsource'). User forced SSE transport in an environment that lacks it.

Related errors


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

Appendix: source

Thrown at src/SignalR/clients/ts/signalr/src/HttpConnection.ts:535

        }

        if (transportExceptions.length > 0) {
            return Promise.reject(new AggregateErrors(`Unable to connect to the server with any of the available transports. ${transportExceptions.join(" ")}`, transportExceptions));
        }
        return Promise.reject(new Error("None of the transports supported by the client are supported by the server."));
    }

    private _constructTransport(transport: HttpTransportType): ITransport {
        switch (transport) {
            case HttpTransportType.WebSockets:
                if (!this._options.WebSocket) {
                    throw new Error("'WebSocket' is not supported in your environment.");
                }
                return new WebSocketTransport(this._httpClient, this._accessTokenFactory, this._logger, this._options.logMessageContent!,
                    this._options.WebSocket, this._options.headers || {});
            case HttpTransportType.ServerSentEvents:
                if (!this._options.EventSource) {
                    throw new Error("'EventSource' is not supported in your environment.");
                }
                return new ServerSentEventsTransport(this._httpClient, this._httpClient._accessToken, this._logger, this._options);
            case HttpTransportType.LongPolling:
                return new LongPollingTransport(this._httpClient, this._logger, this._options);
            default:
                throw new Error(`Unknown transport: ${transport}.`);
        }
    }

    private _startTransport(url: string, transferFormat: TransferFormat): Promise<void> {
        this.transport!.onreceive = this.onreceive;
        if (this.features.reconnect) {
            this.transport!.onclose = async (e) => {
                let callStop = false;
                if (this.features.reconnect) {
                    try {
                        this.features.disconnected();
                        await this.transport!.connect(url, transferFormat);

View on GitHub (pinned to 3600ca084e)