twentyhq/twenty · error · Error

url or fetcher is required

Error message

url or fetcher is required

What it means

Generated genql code in the Twenty client SDK: `createFetcher` requires at least one transport — either a GraphQL endpoint `url` or a custom `fetcher` function. If neither is supplied in the `ClientOptions`, it throws immediately at client construction. This is a programmer error in how the SDK consumer built the client, not a runtime/network issue.

Source

Thrown at packages/twenty-client-sdk/src/generate/genql/runtime/fetcher.ts:30

    batchInterval?: number // ms
    maxBatchSize?: number
}

const DEFAULT_BATCH_OPTIONS = {
    maxBatchSize: 10,
    batchInterval: 40,
}

export const createFetcher = ({
    url,
    headers = {},
    fetcher,
    fetch: _fetch,
    batch = false,
    ...rest
}: ClientOptions): Fetcher => {
    if (!url && !fetcher) {
        throw new Error('url or fetcher is required')
    }
    if (!fetcher) {
        fetcher = async (body) => {
            let headersObject =
                typeof headers == 'function' ? await headers() : headers
            headersObject = headersObject || {}
            if (typeof fetch === 'undefined' && !_fetch) {
                throw new Error(
                    'Global `fetch` function is not available, pass a fetch polyfill to Genql `createClient`',
                )
            }
            let fetchImpl = _fetch || fetch
            const res = await fetchImpl(url!, {
                headers: {
                    'Content-Type': 'application/json',
                    ...headersObject,
                },
                method: 'POST',

View on GitHub (pinned to 1f5dd2bbd2)

Solutions

  1. Pass a non-empty `url` to `createClient`, e.g. `createClient({ url: 'https://api.twenty.com/graphql', headers })`.
  2. If you intend to supply your own transport, pass the `fetcher` option instead of `url`.
  3. When reading the URL from an env var, validate it is non-empty before constructing the client (fail fast with a clear config error).
  4. Check the type of the config object — `url` must be a string, not an object or undefined.

Example fix

// before
const client = createClient({
  headers: { Authorization: `Bearer ${token}` },
  // url accidentally omitted
});

// after
const endpoint = process.env.TWENTY_GRAPHQL_URL;
if (!endpoint) throw new Error('TWENTY_GRAPHQL_URL must be set');
const client = createClient({
  url: endpoint,
  headers: { Authorization: `Bearer ${token}` },
});
Defensive patterns

Strategy: validation

Validate before calling

const endpoint = process.env.TWENTY_GRAPHQL_URL;
if (!endpoint) {
  throw new Error('TWENTY_GRAPHQL_URL must be set to construct the SDK client');
}
const client = createClient({ url: endpoint, headers });

Type guard

const hasClientTransport = (
  opts: Partial<ClientOptions>,
): opts is { url: string } | { fetcher: Fetcher } =>
  (typeof opts.url === 'string' && opts.url.length > 0) || typeof opts.fetcher === 'function';

Prevention

When it happens

Trigger: Calling `createClient({})` or `createClient({ headers })` without a `url` or `fetcher`; destructuring a config object that omitted both; passing `url: undefined`/`url: ''` (falsy) and no fetcher.

Common situations: Building a client from an env var that was undefined at construction time (`url: process.env.GRAPHQL_URL` when the var is unset), a refactor that dropped the url argument, or using a custom fetcher pattern but forgetting to pass the fetcher option.

Related errors


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