PaddlePaddle/PaddleOCR · error

worker mode does not support a custom fetch implementation.

Error message

worker mode does not support a custom fetch implementation.

What it means

PaddleOCR.create() throws this when you enable worker mode (options.worker is true or an options object) and also pass a custom fetch implementation (options.fetch). In worker mode the pipeline runs inside a Web Worker and fetch cannot be serialized or transferred across the worker boundary, so the combination is rejected up front rather than silently ignored.

Source

Thrown at paddleocr-js/packages/core/src/pipelines/ocr/index.ts:80

  [key: string]: unknown;
}

export class PaddleOCR extends OcrPipelineRunner {
  constructor(options: OcrPipelineRunnerOptions) {
    super({
      ...options,
      ensureServedFromHttp,
      sourceToMat
    });
  }

  static async create(
    options: PaddleOCRCreateOptions = {}
  ): Promise<PaddleOCR | WorkerBackedPaddleOCR> {
    const workerOptions = resolveWorkerOptions(options.worker);
    if (workerOptions.enabled && options.fetch) {
      throw new Error("worker mode does not support a custom fetch implementation.");
    }

    const resolvedOptions = resolvePaddleOCROptions(options);
    const instance = workerOptions.enabled
      ? createWorkerBackedPaddleOCR(resolvedOptions, {
          createWorker: workerOptions.createWorker ?? undefined
        })
      : new PaddleOCR({
          ...resolvedOptions,
          fetch: options.fetch
        });

    if (options.initialize !== false) {
      await instance.initialize();
    }
    return instance;
  }
}

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Remove the fetch option when worker mode is enabled; the worker performs its own fetches.
  2. If you need custom networking, keep worker disabled (worker: false or unset) so fetch is honored on the main thread.
  3. If the custom fetch exists for asset URL rewriting, instead override the model/asset URLs via model selection options (e.g. *_model_dir / ModelAsset) which are plain data and worker-safe.

Example fix

// before
const ocr = await PaddleOCR.create({ worker: true, fetch: authedFetch });

// after
const ocr = await PaddleOCR.create({ worker: true });
// or keep custom fetch on the main thread:
const ocr = await PaddleOCR.create({ fetch: authedFetch });
Defensive patterns

Strategy: validation

Validate before calling

// Before create(): worker + fetch are mutually exclusive
const wantsWorker = options.worker === true || (typeof options.worker === 'object' && options.worker !== null);
if (wantsWorker && options.fetch) {
  throw new TypeError('Custom fetch is not supported with worker: true. Remove fetch or disable worker mode.');
}

Type guard

function isSafeCreateOptions(o: { worker?: unknown; fetch?: unknown }): boolean {
  const workerEnabled = o.worker === true || (typeof o.worker === 'object' && o.worker !== null);
  return !(workerEnabled && o.fetch != null);
}

Try / catch

try {
  const ocr = await PaddleOCR.create(opts);
} catch (e) {
  if (e instanceof Error && e.message.includes('does not support a custom fetch')) {
    // retry without fetch (worker performs its own fetching)
    const { fetch: _f, ...rest } = opts;
    return PaddleOCR.create(rest);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling PaddleOCR.create({ worker: true, fetch: myFetch }) or PaddleOCR.create({ worker: { createWorker: () => new Worker(...) }, fetch: customFetch }). resolveWorkerOptions() returns enabled=true and options.fetch is truthy.

Common situations: Adding a fetch wrapper (auth headers, proxying, offline caching) to an existing integration and then turning on worker mode for performance; copying a main-thread configuration object into a worker-mode create() call.

Related errors


AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14). Data as JSON: /api/errors/9cb2ac63884bfa32. Report an issue: GitHub.