twentyhq/twenty · critical · Error

Global `fetch` function is not available, pass a fetch imple

Error message

Global `fetch` function is not available, pass a fetch implementation to the Twenty client

What it means

Thrown by TwentyClient.executeGraphqlRequest (twenty-client-template.ts:303-308) when this.fetchImplementation is falsy at request time. The client only stores a fetch implementation if one was passed explicitly or `globalThis.fetch` existed when the client was constructed — otherwise it is null and every GraphQL call aborts.

Source

Thrown at packages/twenty-client-sdk/src/generate/twenty-client-template.ts:304

      }
    }

    return this.assertResponseIsSuccessful(firstResponse);
  }

  private async executeGraphqlRequest({
    operation,
    headers,
    requestInit,
    token,
  }: {
    operation: GraphqlOperation | GraphqlOperation[] | FormData;
    headers?: HeadersInit;
    requestInit?: RequestInit;
    token: string | null;
  }): Promise<GraphqlResponse> {
    if (!this.fetchImplementation) {
      throw new Error(
        'Global `fetch` function is not available, ' +
          'pass a fetch implementation to the Twenty client',
      );
    }

    const resolvedHeaders = await this.resolveHeaders();
    const requestHeaders = new Headers(resolvedHeaders);

    if (headers) {
      new Headers(headers).forEach((value, key) =>
        requestHeaders.set(key, value),
      );
    }

    if (operation instanceof FormData) {
      requestHeaders.delete('Content-Type');
    } else {
      requestHeaders.set('Content-Type', 'application/json');

View on GitHub (pinned to 1f5dd2bbd2)

Solutions

  1. Upgrade to Node.js 18+ where globalThis.fetch is built in.
  2. Pass an explicit fetch implementation: `new TwentyClient({ fetch: crossFetch, ... })` (or undici, node-fetch, whatwg-fetch).
  3. In tests, set globalThis.fetch = require('node-fetch') or jest.polyfill fetch before constructing the client.
  4. Confirm the polyfill is imported before TwentyClient instantiation.

Example fix

// before
const client = new TwentyClient({ apiUrl, accessToken });
// after
import fetch from 'node-fetch';
const client = new TwentyClient({ apiUrl, accessToken, fetch });
Defensive patterns

Strategy: validation

Validate before calling

const fetchImpl =
  typeof globalThis.fetch === 'function'
    ? globalThis.fetch
    : (await import('node-fetch')).default;
const client = new TwentyClient({ apiUrl, accessToken, fetch: fetchImpl });

Type guard

const hasGlobalFetch = (): boolean => typeof globalThis.fetch === 'function';

Try / catch

try {
  await client.someQuery();
} catch (err) {
  if (err.message.includes('Global `fetch` function is not available')) {
    // pass a fetch polyfill to TwentyClient
  }
  throw err;
}

Prevention

When it happens

Trigger: Constructing TwentyClient in an environment without a global fetch (Node.js < 18, older runtimes, some sandboxed contexts) and not passing a `fetch` option. The first GraphQL call then hits the guard.

Common situations: Running the SDK on Node 16 or 17 (fetch landed as unflagged global in Node 18); using jsdom or a test environment with fetch not polyfilled; SSR/build-time invocations in tooling that strips fetch; bundlers that tree-shake the global.

Related errors


AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12). Data as JSON: /api/errors/f29bb1bc6afd9d19. Report an issue: GitHub.