PaddlePaddle/PaddleOCR · error · Error
Asset "${assetName}" must define url.
Error message
Asset "${assetName}" must define url. What it means
Thrown by normalizeModelAsset() when the asset entry is an object but its url field is missing, empty, or not a non-empty string. The object form of an asset exists solely to carry a URL to a tar model bundle, so the url must be a non-empty string. This fires before any fetch, catching malformed config early.
Source
Thrown at paddleocr-js/packages/core/src/resources/model-asset.ts:73
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.");
}
return Object.fromEntries(
assetEntries.map(([assetName, asset]) => [assetName, normalizeModelAsset(assetName, asset)])View on GitHub (pinned to 2661c7c0ef)
Solutions
- Set a non-empty url string: assets: { det: { url: "https://..." } }
- Check for typos in the key name (must be exactly url)
- Assert the URL variable is a non-empty string before building the config
Example fix
// before
const ocr = await PaddleOCR.create({ assets: { det: { url: process.env.DET_URL } } }); // env unset -> throws
// after
if (!process.env.DET_URL) throw new Error("DET_URL is required");
const ocr = await PaddleOCR.create({ assets: { det: { url: process.env.DET_URL } } }); Defensive patterns
Strategy: validation
Validate before calling
function hasNonEmptyUrl(asset: unknown): boolean {
return (
typeof asset === "object" && asset !== null &&
typeof (asset as Record<string, unknown>).url === "string" &&
((asset as Record<string, unknown>).url as string).length > 0
);
} Type guard
function isUrlAsset(v: unknown): v is { url: string } {
return typeof (v as { url?: unknown })?.url === "string" && (v as { url: string }).url.length > 0;
} Prevention
- Assert env-derived URLs are non-empty strings before building config
- Use exact key 'url' (not uri/src/path)
- Fail fast in app bootstrap when required URL env vars are missing
When it happens
Trigger: Passing { det: {} }, { det: { url: "" } }, or { det: { url: undefined } }; building the URL from a variable that is undefined at runtime; trailing-comma or key-typo objects like { uri: "..." }.
Common situations: Template-literal URLs where an env var is unset producing "undefined" or empty string; key renamed during a refactor (src -> url); config merging that drops the url field.
Related errors
- Asset "${assetName}" references unknown model asset "${asset
- Asset "${assetName}" must be an object.
- 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/1fce072ad13264f6.
Report an issue: GitHub.