microsoft/playwright · error · Error

Route from har is not supported in thin clients

Error message

Route from har is not supported in thin clients

What it means

Thrown by BrowserContext.routeFromHAR() when the connection's localUtils() is null, which happens in thin/remote clients. HAR routing requires the LocalUtils server-side object to parse and serve the HAR file; thin clients don't host it. The guard is `if (!localUtils)`.

Source

Thrown at packages/playwright-core/src/client/browserContext.ts:410

    this._bindings.set(name, binding);
    return DisposableObject.from(result.disposable);
  }

  async route(url: URLMatch, handler: network.RouteHandlerCallback, options: { times?: number } = {}): Promise<DisposableStub> {
    this._routes.unshift(new network.RouteHandler(this._options.baseURL, url, handler, options.times));
    await this._updateInterceptionPatterns({ title: 'Route requests' });
    return new DisposableStub(() => this.unroute(url, handler));
  }

  async routeWebSocket(url: URLMatch, handler: network.WebSocketRouteHandlerCallback): Promise<void> {
    this._webSocketRoutes.unshift(new network.WebSocketRouteHandler(this._options.baseURL, url, handler));
    await this._updateWebSocketInterceptionPatterns({ title: 'Route WebSockets' });
  }

  async routeFromHAR(har: string, options: { url?: string | RegExp, notFound?: 'abort' | 'fallback', update?: boolean, updateContent?: 'attach' | 'embed', updateMode?: 'minimal' | 'full' } = {}): Promise<void> {
    const localUtils = this._connection.localUtils();
    if (!localUtils)
      throw new Error('Route from har is not supported in thin clients');
    if (options.update) {
      await this.tracing._recordIntoHAR(har, null, options);
      return;
    }
    const harRouter = await HarRouter.create(localUtils, har, options.notFound || 'abort', { urlMatch: options.url });
    this._harRouters.push(harRouter);
    await harRouter.addContextRoute(this);
  }

  private _disposeHarRouters() {
    this._harRouters.forEach(router => router.dispose());
    this._harRouters = [];
  }

  async unrouteAll(options?: { behavior?: 'wait'|'ignoreErrors'|'default' }): Promise<void> {
    await this._unrouteInternal(this._routes, [], options?.behavior);
    this._disposeHarRouters();
  }

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Run the browser locally (launch/launchPersistentContext) where localUtils is present.
  2. On the remote server, ensure a full (non-thin) Playwright build is serving the connection.
  3. Replace HAR routing with route() handlers that don't need localUtils.

Example fix

// before
const browser = await playwright.chromium.connect(wsEndpoint);
const ctx = await browser.newContext();
await ctx.routeFromHAR('rec.har');
// after
const browser = await playwright.chromium.launch();
const ctx = await browser.newContext();
await ctx.routeFromHAR('rec.har');
Defensive patterns

Strategy: type-guard

Validate before calling

const localUtils = (context as any)._connection?.localUtils?.();
if (!localUtils)
  throw new Error('routeFromHAR requires a local (non-thin) connection.');

Type guard

function supportsHarRouting(ctx: any): boolean {
  return !!ctx?._connection?.localUtils?.();
}

Prevention

When it happens

Trigger: Calling `context.routeFromHAR('rec.har')` after connecting via BrowserType.connect() to a remote endpoint, or in playwright-client thin mode. localUtils() returns null because the LocalUtils object lives only on the host that owns the registry.

Common situations: Moving tests from local launch to a remote browser grid (Browserless, internal Selenium grid) without realizing HAR routing needs host-side support; mixing thin client with full client features.

Related errors


AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12). Data as JSON: /api/errors/45a7ceab91e417bb. Report an issue: GitHub.