{"record":{"id":"9864b83bc8c24331","repo":"PaddlePaddle/PaddleOCR","slug":"kind-model-requires-a-non-empty-model-entry-p-9864b8","errorCode":null,"errorMessage":"${kind} model requires a non-empty ${MODEL_ENTRY_PATHS.config} resource.","messagePattern":"(.+?) model requires a non-empty (.+?) resource\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"paddleocr-js/packages/core/src/resources/model-asset.ts","lineNumber":111,"sourceCode":"}\n\n// --- Model loading ---\n\nexport function getModelEntryPath(slot: string): string | null {\n  return MODEL_ENTRY_PATHS[slot] || null;\n}\n\nexport function assertModelResourceSlot(kind: string, slot: string, value: unknown): void {\n  if (slot === \"model\") {\n    if (!(value instanceof Uint8Array) || value.byteLength === 0) {\n      throw new Error(`${kind} model requires a non-empty ${MODEL_ENTRY_PATHS.model} resource.`);\n    }\n    return;\n  }\n\n  if (slot === \"config\") {\n    if (typeof value !== \"string\" || value.trim().length === 0) {\n      throw new Error(`${kind} model requires a non-empty ${MODEL_ENTRY_PATHS.config} resource.`);\n    }\n    return;\n  }\n\n  throw new Error(`Unsupported model resource slot \"${slot}\".`);\n}\n\nexport function assertModelResources(kind: string, resources: Record<string, unknown>): void {\n  for (const [slot, value] of Object.entries(resources)) {\n    assertModelResourceSlot(kind, slot, value);\n  }\n}\n\n// --- Model loading (fetch + tar extraction) ---\n\nimport { extractTarEntries, pickTarEntry } from \"./tar\";\n\nexport async function loadModelAsset(","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/paddleocr-js/packages/core/src/resources/model-asset.ts#L93-L129","documentation":"Thrown by assertModelResourceSlot() when the \"config\" slot is not a string or is whitespace-only after decoding. Every model bundle must ship a textual config entry (path MODEL_ENTRY_PATHS.config) alongside the model bytes; the runtime reads it to build the inference graph. An empty/missing config means the tar lacks the expected config file or it decoded to empty text.","triggerScenarios":"A tar bundle that omits the config entry file; a config file that is empty or all whitespace; binary garbage placed at the config path so TextDecoder output is empty; hand-built resources where configText was never populated.","commonSituations":"Repackaging official models and forgetting the .yml/.json config; a proxy rewriting or truncating text assets; version mismatch where the entry filename changed between releases.","solutions":["Inspect the tar (tar -tf bundle.tar) and confirm the config entry exists at the expected path with non-trivial size","Re-download or re-package the bundle from official sources","If generating resources yourself, decode the config entry into a non-empty string before passing to the runtime"],"exampleFix":"# before\n# tar contains only weights, no config file -> assert fails\n\n# after\n# ensure the config entry exists:\ntar -tf bundle.tar\n# .../inference.yml  (non-empty)\n# .../inference.pdmodel","handlingStrategy":"validation","validationCode":"function isValidConfigSlot(v: unknown): boolean {\n  return typeof v === \"string\" && v.trim().length > 0;\n}","typeGuard":"function isNonEmptyText(v: unknown): v is string {\n  return typeof v === \"string\" && v.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Confirm the config entry exists and is non-empty when repackaging tars","Use official bundles unless you control packaging","Smoke-test custom bundles in CI before deployment"],"tags":["model","validation","tar","config"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}