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.

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.

Appendix: 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)