{"record":{"id":"371980e6f50e7b79","repo":"PaddlePaddle/PaddleOCR","slug":"text-detection-model-dir-requires-text-detection-m","errorCode":null,"errorMessage":"text_detection_model_dir requires text_detection_model_name.","messagePattern":"text_detection_model_dir requires text_detection_model_name\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"paddleocr-js/packages/core/src/pipelines/ocr/shared.ts","lineNumber":497,"sourceCode":"  const modelSelection: Record<string, string | null> = {};\n  const assets: Record<string, ModelAsset> = {};\n  let hasAnyOption = false;\n\n  for (const role of OCR_MODEL_ROLES) {\n    const modelName = readAliasedOption(options, role.nameAliases, role.nameLabel) as\n      | string\n      | undefined;\n    const asset = readAliasedOption(options, role.assetAliases, role.assetLabel) as\n      | ModelAsset\n      | undefined;\n\n    if (modelName !== undefined) {\n      modelSelection[role.selectionKey] = modelName;\n      hasAnyOption = true;\n    }\n    if (asset !== undefined) {\n      if (modelName === undefined) {\n        throw new Error(role.assetRequirementError);\n      }\n      assets[role.assetKey] = asset;\n      hasAnyOption = true;\n    }\n  }\n\n  if (!hasAnyOption) {\n    return null;\n  }\n\n  return {\n    modelSelection,\n    assets\n  };\n}\n\nfunction resolveBaseModelSelection(\n  options: Record<string, unknown>,","sourceCodeStart":479,"sourceCodeEnd":515,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/paddleocr-js/packages/core/src/pipelines/ocr/shared.ts#L479-L515","documentation":"When explicit model options are detected, getExplicitModelSelection() iterates model roles. For the text detection role, if an asset option (text_detection_model_dir or its aliases) is present but the companion name option (text_detection_model_name) is absent, it throws role.assetRequirementError, whose text is 'text_detection_model_dir requires text_detection_model_name.'. The name is required because it must match the inference.yml validation later.","triggerScenarios":"Passing { textDetectionModelDir: '/models/det/' } (or the snake_case alias) without textDetectionModelName to PaddleOCR.create().","commonSituations":"Assuming a bare directory is enough to load a self-hosted model; migrating from an API that only took paths.","solutions":["Add textDetectionModelName matching the model_name declared in that directory's inference.yml.","Or drop the dir option to use the default hosted detection model."],"exampleFix":"// before\nconst ocr = await PaddleOCR.create({ textDetectionModelDir: '/models/det/' });\n\n// after\nconst ocr = await PaddleOCR.create({\n  textDetectionModelName: 'PP-OCRv5_mobile_det',\n  textDetectionModelDir: '/models/det/'\n});","handlingStrategy":"validation","validationCode":"if (opts.textDetectionModelDir !== undefined && (opts.textDetectionModelName ?? opts.text_detection_model_name) === undefined) {\n  throw new TypeError('textDetectionModelDir requires textDetectionModelName');\n}","typeGuard":"function isDetDirWithName(o: Record<string, unknown>): boolean {\n  const dir = o.textDetectionModelDir ?? o.text_detection_model_dir;\n  const name = o.textDetectionModelName ?? o.text_detection_model_name;\n  return dir === undefined || typeof name === 'string';\n}","tryCatchPattern":"try {\n  const ocr = await PaddleOCR.create(opts);\n} catch (e) {\n  if (e instanceof Error && e.message === 'text_detection_model_dir requires text_detection_model_name.') {\n    opts = { ...opts, textDetectionModelName: 'PP-OCRv5_mobile_det' };\n    return PaddleOCR.create(opts);\n  }\n  throw e;\n}","preventionTips":["Treat (name, dir) as one unit in your config type: model: { name: string; dir?: string }.","Add a lint/assert step over user-supplied OCR config rejecting dir-without-name."],"tags":["model-selection","configuration","detection"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}