{"record":{"id":"3f1b369ae6f01517","repo":"PaddlePaddle/PaddleOCR","slug":"ocr-pipeline-config-must-define-both-submodules-t","errorCode":null,"errorMessage":"OCR pipeline config must define both \"SubModules.TextDetection\" and \"SubModules.TextRecognition\".","messagePattern":"OCR pipeline config must define both \"SubModules\\.TextDetection\" and \"SubModules\\.TextRecognition\"\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"paddleocr-js/packages/core/src/pipelines/ocr/config.ts","lineNumber":151,"sourceCode":"export function normalizeOcrPipelineConfig(input: unknown): NormalizedPipelineConfig {\n  const config = parsePipelineConfigInput(input);\n  const pipelineName = (config.pipeline_name as string | undefined) ?? SUPPORTED_PIPELINE_NAME;\n\n  if (pipelineName !== SUPPORTED_PIPELINE_NAME) {\n    throw new Error(\n      `Unsupported pipeline_name \"${pipelineName}\". PaddleOCR.js currently supports only \"${SUPPORTED_PIPELINE_NAME}\".`\n    );\n  }\n\n  const warnings: string[] = [];\n  const subModules = isPlainObject(config.SubModules) ? config.SubModules : {};\n  const textDetection = isPlainObject(subModules.TextDetection) ? subModules.TextDetection : null;\n  const textRecognition = isPlainObject(subModules.TextRecognition)\n    ? subModules.TextRecognition\n    : null;\n\n  if (!textDetection || !textRecognition) {\n    throw new Error(\n      'OCR pipeline config must define both \"SubModules.TextDetection\" and \"SubModules.TextRecognition\".'\n    );\n  }\n\n  const useDocPreprocessor = Boolean(config.use_doc_preprocessor);\n  const useTextlineOrientation = Boolean(config.use_textline_orientation);\n  const subPipelines = config.SubPipelines as YamlObject | undefined;\n  const docPreprocessor = isPlainObject(subPipelines?.DocPreprocessor)\n    ? subPipelines.DocPreprocessor\n    : null;\n  const textLineOrientation = isPlainObject(subModules.TextLineOrientation)\n    ? subModules.TextLineOrientation\n    : null;\n\n  if (useDocPreprocessor || docPreprocessor) {\n    addFeatureWarning(warnings, \"DocPreprocessor\", \"config will be ignored for now\");\n  }\n  if (useTextlineOrientation || textLineOrientation) {","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/paddleocr-js/packages/core/src/pipelines/ocr/config.ts#L133-L169","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure the config has SubModules with both TextDetection and TextRecognition keys, each a mapping","Check YAML indentation — SubModules must be top-level and the module keys nested under it","If you only need recognition, this pipeline API still requires a det module; use the lower-level rec model API instead"],"exampleFix":"# before\nSubModules:\n  TextRecognition:\n    model_name: PP-OCRv5_mobile_rec\n\n# after\nSubModules:\n  TextDetection:\n    model_name: PP-OCRv5_mobile_det\n  TextRecognition:\n    model_name: PP-OCRv5_mobile_rec","handlingStrategy":"validation","validationCode":"const sub = config.SubModules;\nconst hasDet = !!sub && typeof sub === \"object\" && \"TextDetection\" in sub;\nconst hasRec = !!sub && typeof sub === \"object\" && \"TextRecognition\" in sub;\nif (!hasDet || !hasRec) {\n  throw new Error(\"Config must define SubModules.TextDetection and SubModules.TextRecognition\");\n}","typeGuard":"function hasRequiredSubModules(config: unknown): boolean {\n  const sub = (config as any)?.SubModules;\n  return typeof sub?.TextDetection === \"object\" && typeof sub?.TextRecognition === \"object\";\n}","tryCatchPattern":null,"preventionTips":["Validate SubModules shape before passing config to the pipeline","Watch YAML indentation so module keys land under SubModules, not beside it","Rec-only workflows are not supported by this pipeline entry point"],"tags":["paddleocr","config","yaml","pipeline","validation"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}