{"record":{"id":"2a7d7225744a0e03","repo":"jackwener/OpenCLI","slug":"flathub-returned-404-for-url","errorCode":null,"errorMessage":"Flathub returned 404 for ${url}.","messagePattern":"Flathub returned 404 for (.+?)\\.","errorType":"exception","errorClass":"EmptyResultError","httpStatus":404,"severity":"error","filePath":"clis/flathub/utils.js","lineNumber":63,"sourceCode":"}\n\nexport async function flathubFetch(url, label, init) {\n    let resp;\n    try {\n        resp = await fetch(url, {\n            method: init?.method ?? 'GET',\n            headers: { 'user-agent': UA, accept: 'application/json', ...(init?.headers ?? {}) },\n            body: init?.body,\n        });\n    }\n    catch (err) {\n        throw new CommandExecutionError(\n            `${label} request failed: ${err?.message ?? err}`,\n            'Check that flathub.org is reachable from this network.',\n        );\n    }\n    if (resp.status === 404) {\n        throw new EmptyResultError(label, `Flathub returned 404 for ${url}.`);\n    }\n    if (resp.status === 429) {\n        throw new CommandExecutionError(`${label} returned HTTP 429 (rate limited)`);\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;\n}\n\nexport function joinList(value, max = 10) {","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/flathub/utils.js#L45-L81","documentation":"flathubFetch maps HTTP 404 from flathub.org to EmptyResultError with the message 'Flathub returned 404 for <url>'. It means the requested resource (typically GET /appstream/<appId>) does not exist on Flathub — almost always an appId that is not in the registry.","triggerScenarios":"Calling an app-detail adapter with a well-formed but nonexistent appId (e.g. org.mozilla.firefoxx); an app that was removed/renamed on Flathub; a typo in one ID segment; requesting an app hosted only outside Flathub.","commonSituations":"Hard-coded appIds in scripts that became stale after a rename; IDs from third-party docs; searching found the app elsewhere but the Flathub ID differs; clipboard truncation dropping a segment.","solutions":["Run `flathub search <name>` to get the current correct appId and retry","Verify the exact ID spelling segment by segment (org.vendor.AppName)","Check the app page at https://flathub.org/apps/<appId> to confirm it exists","Handle EmptyResultError in your code if IDs come from user input, and surface a 'not found' message"],"exampleFix":"// before\nawait appInfo('org.gnome.calculator'); // wrong case\n// after\nawait appInfo('org.gnome.Calculator');","handlingStrategy":"try-catch","validationCode":"const APP_ID_RE = /^[A-Za-z][A-Za-z0-9_-]*(?:\\.[A-Za-z0-9_][A-Za-z0-9_-]*){1,}$/;\nif (!APP_ID_RE.test((appId ?? '').trim())) throw new Error('malformed appId — resolve it via flathub search first');","typeGuard":"null","tryCatchPattern":"try {\n  const info = await appInfo(appId);\n} catch (err) {\n  if (err instanceof EmptyResultError) {\n    console.log(`App \"${appId}\" not found on Flathub — run flathub search to get the correct ID`);\n  } else throw err;\n}","preventionTips":["Resolve appIds dynamically via `flathub search` instead of hard-coding them","Handle EmptyResultError explicitly when IDs come from user input or external data","Re-verify hard-coded IDs periodically — apps get renamed or removed","Check https://flathub.org/apps/<appId> in a browser when a 404 persists"],"tags":["http-404","not-found","http-api"],"backgroundTag":"http-404-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}