PaddlePaddle/PaddleOCR · error · Error
Asset "${assetName}" must be an object.
Error message
Asset "${assetName}" must be an object. What it means
Thrown by normalizeModelAsset() when the asset value is neither a non-empty string (built-in name) nor a plain object - e.g. a number, boolean, null, or array. Each asset entry must be a preset name string or an object with a url field; anything else is rejected at normalization time before any network activity.
Source
Thrown at paddleocr-js/packages/core/src/resources/model-asset.ts:70
return typeof value === "string" && value.length > 0;
}
function isObject(value: unknown): value is Record<string, unknown> {
return Boolean(value && typeof value === "object" && !Array.isArray(value));
}
export function normalizeModelAsset(assetName: string, asset: unknown): ModelAsset {
if (isNonEmptyString(asset)) {
const resolvedAsset = DEFAULT_MODEL_ASSETS[asset];
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime guard for missing Record key
if (!resolvedAsset) {
throw new Error(`Asset "${assetName}" references unknown model asset "${asset}".`);
}
return { url: resolvedAsset.url };
}
if (!isObject(asset)) {
throw new Error(`Asset "${assetName}" must be an object.`);
}
if (!isNonEmptyString(asset.url)) {
throw new Error(`Asset "${assetName}" must define url.`);
}
return {
url: asset.url
};
}
export function normalizeAssets(
assets: Record<string, unknown> | undefined
): Record<string, ModelAsset> {
const assetEntries = Object.entries(assets || {});
if (assetEntries.length === 0) {
throw new Error("Assets must define at least one asset.");
}View on GitHub (pinned to 2661c7c0ef)
Solutions
- Set each asset entry to a string preset name or { url: "..." }
- Validate the config shape before calling create() (see type guard)
- If the value comes from JSON, add a schema check at load time
Example fix
// before
const ocr = await PaddleOCR.create({ assets: { det: null } });
// after
const ocr = await PaddleOCR.create({ assets: { det: { url: "https://host/det.tar" } } }); Defensive patterns
Strategy: type-guard
Validate before calling
function isPlainObject(v: unknown): v is Record<string, unknown> {
return Boolean(v) && typeof v === "object" && !Array.isArray(v);
} Type guard
function isAssetShape(v: unknown): v is string | { url: string } {
if (typeof v === "string") return v.length > 0;
return isPlainObject(v) && typeof (v as any).url === "string" && (v as any).url.length > 0;
} Prevention
- Type your config as Record<string, string | { url: string }> so TS rejects numbers/null
- Validate parsed JSON config before passing to create()
When it happens
Trigger: Passing assets: { det: 42 }, { det: null }, { det: ["https://..."] }, or spreading undefined over a default entry; JSON configs where the asset got serialized incorrectly.
Common situations: Config built from environment variables without casting ("" or numbers); YAML/JSON pipeline where the asset key is present but the value is a list or null; accidental nesting like { det: { model: { url } } }.
Related errors
- Asset "${assetName}" references unknown model asset "${asset
- Asset "${assetName}" must define url.
- Assets must define at least one asset.
- OCR pipeline config text must decode to an object.
- OCR pipeline config must be an object or YAML text.
AI-assisted analysis of PaddlePaddle/PaddleOCR@2661c7c0ef (2026-08-14).
Data as JSON: /api/errors/f4c3c32aee207d88.
Report an issue: GitHub.