OrchardCMS/OrchardCore · critical · Error

No usable HttpClient found.

Error message

No usable HttpClient found.

What it means

HttpConnection's constructor throws 'No usable HttpClient found.' when neither the WHATWG fetch API (fetch/AbortController) nor XMLHttpRequest is available in the runtime. The SignalR client needs at least one of these to perform HTTP requests, and it fails at connection construction rather than at first send.

Solutions

  1. Install a fetch polyfill (e.g. whatwg-fetch, node-fetch assigned to globalThis) before importing/using the client
  2. In Node, import '@microsoft/signalr' (the Node build) instead of the browser 'signalr.js' bundle
  3. Ensure the test/SSR environment provides fetch or XMLHttpRequest globals
  4. Target a browser that supports fetch (or supply XHR fallback)

Example fix

// before (Node, browser bundle)
import { HubConnectionBuilder } from './wwwroot/Scripts/signalr.js';
// after
import * as signalr from '@microsoft/signalr'; // Node-compatible entry
if (!globalThis.fetch) globalThis.fetch = (await import('node-fetch')).default;
Defensive patterns

Strategy: fallback

Validate before calling

if (typeof fetch === 'undefined' && typeof XMLHttpRequest === 'undefined') throw new Error('SignalR requires fetch or XMLHttpRequest polyfill');

Type guard

const hasHttpStack = () => typeof globalThis.fetch !== 'undefined' || typeof globalThis.XMLHttpRequest !== 'undefined';

Try / catch

try { connection = new HubConnectionBuilder().withUrl(url).build(); } catch (e) { if (e.message === 'No usable HttpClient found.') installPolyfill(); }

Prevention

When it happens

Trigger: Running the browser build of signalr.js in Node.js without a fetch polyfill; very old browsers lacking both fetch and XHR; restricted environments (web workers/SSR) where globals are stripped.

Common situations: Server-side rendering importing the browser bundle; Jest/jsdom tests with outdated environment flags; embedding the client in a sandboxed worker without network globals.

Understand the failure class

Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.

Related errors


AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13). Data as JSON: /api/errors/c4d40635912959e1. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore.Modules/OrchardCore.SignalR/wwwroot/Scripts/signalr.js:816

// The .NET Foundation licenses this file to you under the MIT license.





/** Default implementation of {@link @microsoft/signalr.HttpClient}. */
class DefaultHttpClient extends HttpClient {
    /** Creates a new instance of the {@link @microsoft/signalr.DefaultHttpClient}, using the provided {@link @microsoft/signalr.ILogger} to log messages. */
    constructor(logger) {
        super();
        if (typeof fetch !== "undefined" || Platform.isNode) {
            this._httpClient = new FetchHttpClient(logger);
        }
        else if (typeof XMLHttpRequest !== "undefined") {
            this._httpClient = new XhrHttpClient(logger);
        }
        else {
            throw new Error("No usable HttpClient found.");
        }
    }
    /** @inheritDoc */
    send(request) {
        // Check that abort was not signaled before calling send
        if (request.abortSignal && request.abortSignal.aborted) {
            return Promise.reject(new AbortError());
        }
        if (!request.method) {
            return Promise.reject(new Error("No method defined."));
        }
        if (!request.url) {
            return Promise.reject(new Error("No url defined."));
        }
        return this._httpClient.send(request);
    }
    getCookieString(url) {
        return this._httpClient.getCookieString(url);

View on GitHub (pinned to 4306c0717f)