PaddlePaddle/PaddleOCR · error

OCR pipeline config must define both "SubModules.TextDetecti

Error message

OCR pipeline config must define both "SubModules.TextDetection" and "SubModules.TextRecognition".

What it means

Thrown by normalizeOcrPipelineConfig() when SubModules lacks either TextDetection or TextRecognition (or SubModules itself is missing). These two modules are the minimum for an OCR pipeline — without both, no end-to-end prediction is possible, so the config is rejected at normalization time.

Source

Thrown at paddleocr-js/packages/core/src/pipelines/ocr/config.ts:151

export function normalizeOcrPipelineConfig(input: unknown): NormalizedPipelineConfig {
  const config = parsePipelineConfigInput(input);
  const pipelineName = (config.pipeline_name as string | undefined) ?? SUPPORTED_PIPELINE_NAME;

  if (pipelineName !== SUPPORTED_PIPELINE_NAME) {
    throw new Error(
      `Unsupported pipeline_name "${pipelineName}". PaddleOCR.js currently supports only "${SUPPORTED_PIPELINE_NAME}".`
    );
  }

  const warnings: string[] = [];
  const subModules = isPlainObject(config.SubModules) ? config.SubModules : {};
  const textDetection = isPlainObject(subModules.TextDetection) ? subModules.TextDetection : null;
  const textRecognition = isPlainObject(subModules.TextRecognition)
    ? subModules.TextRecognition
    : null;

  if (!textDetection || !textRecognition) {
    throw new Error(
      'OCR pipeline config must define both "SubModules.TextDetection" and "SubModules.TextRecognition".'
    );
  }

  const useDocPreprocessor = Boolean(config.use_doc_preprocessor);
  const useTextlineOrientation = Boolean(config.use_textline_orientation);
  const subPipelines = config.SubPipelines as YamlObject | undefined;
  const docPreprocessor = isPlainObject(subPipelines?.DocPreprocessor)
    ? subPipelines.DocPreprocessor
    : null;
  const textLineOrientation = isPlainObject(subModules.TextLineOrientation)
    ? subModules.TextLineOrientation
    : null;

  if (useDocPreprocessor || docPreprocessor) {
    addFeatureWarning(warnings, "DocPreprocessor", "config will be ignored for now");
  }
  if (useTextlineOrientation || textLineOrientation) {

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Ensure the config has SubModules with both TextDetection and TextRecognition keys, each a mapping
  2. Check YAML indentation — SubModules must be top-level and the module keys nested under it
  3. If you only need recognition, this pipeline API still requires a det module; use the lower-level rec model API instead

Example fix

# before
SubModules:
  TextRecognition:
    model_name: PP-OCRv5_mobile_rec

# after
SubModules:
  TextDetection:
    model_name: PP-OCRv5_mobile_det
  TextRecognition:
    model_name: PP-OCRv5_mobile_rec
Defensive patterns

Strategy: validation

Validate before calling

const sub = config.SubModules;
const hasDet = !!sub && typeof sub === "object" && "TextDetection" in sub;
const hasRec = !!sub && typeof sub === "object" && "TextRecognition" in sub;
if (!hasDet || !hasRec) {
  throw new Error("Config must define SubModules.TextDetection and SubModules.TextRecognition");
}

Type guard

function hasRequiredSubModules(config: unknown): boolean {
  const sub = (config as any)?.SubModules;
  return typeof sub?.TextDetection === "object" && typeof sub?.TextRecognition === "object";
}

Prevention

When it happens

Trigger: A config defining only SubModules.TextRecognition (rec-only usage); SubModules misspelled (submodules, SubModule); TextDetection present but as a non-object (e.g. a string) so isPlainObject fails and it is treated as null.

Common situations: Trimming a config down for rec-only experiments not supported by this entry point; merging configs that accidentally dropped a SubModules key; YAML indentation putting the modules one level under the wrong parent.

Related errors


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