{"record":{"id":"43d7aaeb7beea29d","repo":"jackwener/OpenCLI","slug":"wikidata-returned-404-for-url","errorCode":null,"errorMessage":"Wikidata returned 404 for ${url}.","messagePattern":"Wikidata returned 404 for (.+?)\\.","errorType":"exception","errorClass":"EmptyResultError","httpStatus":404,"severity":"warning","filePath":"clis/wikidata/utils.js","lineNumber":73,"sourceCode":"            'Expected an ISO 639 language code such as \"en\", \"fr\", \"zh\", \"zh-hans\".',\n        );\n    }\n    return raw;\n}\n\nexport async function wikidataFetch(url, label) {\n    let resp;\n    try {\n        resp = await fetch(url, { headers: { 'user-agent': UA, accept: 'application/json' } });\n    }\n    catch (err) {\n        throw new CommandExecutionError(\n            `${label} request failed: ${err?.message ?? err}`,\n            'Check that www.wikidata.org is reachable from this network.',\n        );\n    }\n    if (resp.status === 404) {\n        throw new EmptyResultError(label, `Wikidata returned 404 for ${url}.`);\n    }\n    if (resp.status === 429) {\n        throw new CommandExecutionError(\n            `${label} returned HTTP 429 (rate limited)`,\n            'Wikidata throttles anonymous traffic; back off and retry.',\n        );\n    }\n    if (!resp.ok) {\n        throw new CommandExecutionError(`${label} returned HTTP ${resp.status}`);\n    }\n    let body;\n    try {\n        body = await resp.json();\n    }\n    catch (err) {\n        throw new CommandExecutionError(`${label} returned malformed JSON: ${err?.message ?? err}`);\n    }\n    return body;","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/wikidata/utils.js#L55-L91","documentation":"wikidataFetch wraps every Wikidata HTTP call. A 404 from the Wikidata API is treated as an EmptyResultError rather than a hard failure, because 404 here means 'entity/URL does not exist' — most commonly a bad Q-ID on Special:EntityData. The library throws it so callers can treat 'not found' as an empty result instead of an error.","triggerScenarios":"Calling wikidataFetch with an entity URL like https://www.wikidata.org/wiki/Special:EntityData/Q999999999.json where the Q-ID does not exist; a mistyped or deleted entity ID reaching the endpoint; a wrong path/hostname in the URL passed to wikidataFetch.","commonSituations":"User pastes an invalid or deleted Wikidata Q-ID (e.g. off-by-one or fabricated ID); a script iterates a stale list of entities where some were merged/redirected and the old ID 404s; constructing the EntityData URL programmatically with a bad ID.","solutions":["Verify the entity ID is a valid existing Q/P/L ID by searching it on www.wikidata.org or via wbsearchentities","Catch EmptyResultError in the calling code and treat it as 'no result' rather than a crash","Check the URL passed to wikidataFetch for typos in the path or hostname"],"exampleFix":"// before\nconst body = await wikidataFetch(`${WIKIDATA_BASE}/wiki/Special:EntityData/${qid}.json`, 'entity');\n// after\nlet body;\ntry {\n  body = await wikidataFetch(`${WIKIDATA_BASE}/wiki/Special:EntityData/${qid}.json`, 'entity');\n} catch (err) {\n  if (err instanceof EmptyResultError) return null; // entity not found\n  throw err;\n}","handlingStrategy":"try-catch","validationCode":"const qid = String(id ?? '').trim().toUpperCase();\nif (!/^[QPL]\\d+$/.test(qid)) throw new Error(`invalid entity id: ${id}`);","typeGuard":"function isEntityId(v) { return typeof v === 'string' && /^[QPL]\\d+$/.test(v.trim().toUpperCase()); }","tryCatchPattern":"try {\n  const body = await wikidataFetch(url, 'entity');\n} catch (err) {\n  if (err instanceof EmptyResultError) return null; // 404 = entity not found\n  throw err;\n}","preventionTips":["Validate Q/P/L IDs with /^[QPL]\\d+$/ before building the URL","Resolve possibly-stale IDs via wbsearchentities first","Treat EmptyResultError as an expected 'no result' outcome, not a crash"],"tags":["http-404","wikidata","empty-result","network"],"backgroundTag":"http-404-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}