PaddlePaddle/PaddleOCR · error

text_recognition_model_dir requires text_recognition_model_n

Error message

text_recognition_model_dir requires text_recognition_model_name.

What it means

Same guard as the detection variant, but for the recognition role: getExplicitModelSelection() found a recognition asset option (text_recognition_model_dir or aliases) without text_recognition_model_name, and throws role.assetRequirementError with this text. The name is needed for inference.yml cross-validation of the loaded package.

Source

Thrown at paddleocr-js/packages/core/src/pipelines/ocr/shared.ts:497

  const modelSelection: Record<string, string | null> = {};
  const assets: Record<string, ModelAsset> = {};
  let hasAnyOption = false;

  for (const role of OCR_MODEL_ROLES) {
    const modelName = readAliasedOption(options, role.nameAliases, role.nameLabel) as
      | string
      | undefined;
    const asset = readAliasedOption(options, role.assetAliases, role.assetLabel) as
      | ModelAsset
      | undefined;

    if (modelName !== undefined) {
      modelSelection[role.selectionKey] = modelName;
      hasAnyOption = true;
    }
    if (asset !== undefined) {
      if (modelName === undefined) {
        throw new Error(role.assetRequirementError);
      }
      assets[role.assetKey] = asset;
      hasAnyOption = true;
    }
  }

  if (!hasAnyOption) {
    return null;
  }

  return {
    modelSelection,
    assets
  };
}

function resolveBaseModelSelection(
  options: Record<string, unknown>,

View on GitHub (pinned to 2661c7c0ef)

Solutions

  1. Add textRecognitionModelName matching the model_name in that directory's inference.yml.
  2. Or remove the dir option to fall back to the default hosted recognition model.

Example fix

// before
const ocr = await PaddleOCR.create({ textRecognitionModelDir: '/models/rec/' });

// after
const ocr = await PaddleOCR.create({
  textRecognitionModelName: 'PP-OCRv5_mobile_rec',
  textRecognitionModelDir: '/models/rec/'
});
Defensive patterns

Strategy: validation

Validate before calling

if (opts.textRecognitionModelDir !== undefined && (opts.textRecognitionModelName ?? opts.text_recognition_model_name) === undefined) {
  throw new TypeError('textRecognitionModelDir requires textRecognitionModelName');
}

Type guard

function isRecDirWithName(o: Record<string, unknown>): boolean {
  const dir = o.textRecognitionModelDir ?? o.text_recognition_model_dir;
  const name = o.textRecognitionModelName ?? o.text_recognition_model_name;
  return dir === undefined || typeof name === 'string';
}

Try / catch

try {
  const ocr = await PaddleOCR.create(opts);
} catch (e) {
  if (e instanceof Error && e.message === 'text_recognition_model_dir requires text_recognition_model_name.') {
    opts = { ...opts, textRecognitionModelName: 'PP-OCRv5_mobile_rec' };
    return PaddleOCR.create(opts);
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing { textRecognitionModelDir: '/models/rec/' } (or its aliases) without textRecognitionModelName to PaddleOCR.create().

Common situations: Self-hosting only the recognition model and passing just its path; fixing the detection pair but forgetting the recognition name after copy-paste.

Related errors


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