jackwener/OpenCLI · warning · EmptyResultError

OSV.dev returned 404 for ${url}.

Error message

OSV.dev returned 404 for ${url}.

What it means

OSV.dev's API endpoint returned HTTP 404 for the requested URL. This library surfaces it as an EmptyResultError because a 404 from api.osv.dev means no vulnerability data exists at that resource (e.g. an unknown vulnerability ID), rather than a transient network failure.

Source

Thrown at clis/osv/utils.js:109

    catch (err) {
        throw new CommandExecutionError(`${label} returned malformed JSON: ${err?.message ?? err}`);
    }
    return body;
}

export async function osvGet(url, label) {
    let resp;
    try {
        resp = await fetch(url, { headers: { 'user-agent': UA, accept: 'application/json' } });
    }
    catch (err) {
        throw new CommandExecutionError(
            `${label} request failed: ${err?.message ?? err}`,
            'Check that api.osv.dev is reachable from this network.',
        );
    }
    if (resp.status === 404) {
        throw new EmptyResultError(label, `OSV.dev returned 404 for ${url}.`);
    }
    if (resp.status === 429) {
        throw new CommandExecutionError(`${label} returned HTTP 429 (rate limited)`);
    }
    if (!resp.ok) {
        throw new CommandExecutionError(`${label} returned HTTP ${resp.status}`);
    }
    return readJson(resp, label);
}

export async function osvPost(url, payload, label) {
    let resp;
    try {
        resp = await fetch(url, {
            method: 'POST',
            headers: { 'user-agent': UA, accept: 'application/json', 'content-type': 'application/json' },
            body: JSON.stringify(payload),
        });

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Verify the vulnerability ID is correct and exists on https://osv.dev (search the ID on the website first)
  2. If the ID is a CVE alias, resolve it to the GHSA/OSV ID that OSV.dev actually indexes and retry
  3. Handle EmptyResultError in the caller and treat it as 'no data' rather than retrying
  4. Check the full URL built by osvGet for encoding mistakes (encodeURIComponent is applied to the id)

Example fix

// before
await osvGet(`${OSV_BASE}/v1/vulns/CVE-2023-123`, 'osv vulnerability CVE-2023-123');
// after
const vuln = await osvGet(`${OSV_BASE}/v1/vulns/ghsa-xxxx`, 'osv vulnerability ghsa-xxxx');
if (!vuln) console.log('No OSV record for that ID');
Defensive patterns

Strategy: try-catch

Validate before calling

if (!/^(CVE|GHSA|OSV|PYSEC|RSA|USN)-/i.test(id)) { throw new Error(`Suspicious vulnerability id: ${id}`); }

Type guard

function hasOsvRecord(v) { return v != null && typeof v === 'object' && typeof v.id === 'string' && v.id.length > 0; }

Try / catch

try {
  const vuln = await vuln(id);
  // use vuln
} catch (e) {
  if (/404/.test(e.message)) return null; // no record
  throw e;
}

Prevention

When it happens

Trigger: osvGet was called with a URL like `${OSV_BASE}/v1/vulns/<id>` (via the `vuln` command) and api.osv.dev responded with status 404 — typically a malformed or non-existent vulnerability ID passed through requireVulnId.

Common situations: Querying a CVE/GHSA/RSA ID that does not exist in OSV.dev or was aliased/withdrawn; a typo in the vulnerability ID; querying an ecosystem-specific ID OSV has never ingested.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/837f228784772fdb. Report an issue: GitHub.