{"record":{"id":"673985d768dd5a97","repo":"jackwener/OpenCLI","slug":"crates-crate","errorCode":null,"errorMessage":"crates crate","messagePattern":"crates crate","errorType":"exception","errorClass":"EmptyResultError","httpStatus":null,"severity":"warning","filePath":"clis/crates/crate.js","lineNumber":31,"sourceCode":"    name: 'crate',\n    access: 'read',\n    description: 'Single crates.io crate metadata (latest version, downloads, license, repo)',\n    domain: 'crates.io',\n    strategy: Strategy.PUBLIC,\n    browser: false,\n    args: [\n        { name: 'name', positional: true, required: true, help: 'crates.io crate name (e.g. \"serde\", \"tokio\")' },\n    ],\n    columns: [\n        'name', 'latestVersion', 'description', 'downloads', 'recentDownloads', 'versions',\n        'license', 'homepage', 'documentation', 'repository', 'keywords', 'categories', 'created', 'updated', 'url',\n    ],\n    func: async (args) => {\n        const name = requireCrateName(args.name);\n        const body = await cratesFetch(`${CRATES_BASE}/api/v1/crates/${encodeURIComponent(name)}`, `crates crate ${name}`);\n        const c = body?.crate;\n        if (!c || !c.id) {\n            throw new EmptyResultError('crates crate', `crates.io returned no metadata for \"${name}\".`);\n        }\n        const versions = Array.isArray(body.versions) ? body.versions : [];\n        const latestRow = versions.find((v) => v.num === c.newest_version)\n            || versions.find((v) => v.num === c.max_stable_version)\n            || versions[0]\n            || {};\n        const keywords = Array.isArray(body.keywords)\n            ? body.keywords.map((k) => k?.keyword || k?.id || '').filter(Boolean).join(', ')\n            : '';\n        const categories = Array.isArray(body.categories)\n            ? body.categories.map((cat) => cat?.category || cat?.slug || '').filter(Boolean).join(', ')\n            : '';\n        return [{\n            name: String(c.name ?? c.id),\n            latestVersion: String(c.newest_version ?? c.max_stable_version ?? c.max_version ?? ''),\n            description: String(c.description ?? '').trim(),\n            downloads: c.downloads != null ? Number(c.downloads) : null,\n            recentDownloads: c.recent_downloads != null ? Number(c.recent_downloads) : null,","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/crates/crate.js#L13-L49","documentation":"The 'crates crate' EmptyResultError is thrown by the crates.io 'crate' subcommand when crates.io responds successfully but contains no crate metadata (body.crate missing or lacking an id), or upstream returns 404 via cratesFetch. It signals 'valid request, no data' rather than a transport failure.","triggerScenarios":"Running `crates crate <name>` where the name does not exist on crates.io (cratesFetch maps the 404 to EmptyResultError), or crates.io returns 200 with unexpected/empty JSON so body?.crate is undefined.","commonSituations":"Typo in the crate name ('tokyio' instead of 'tokio'), a private/removed/yanked-only crate, a name that was never published, or a crates.io API schema change that temporarily breaks the response shape.","solutions":["Check the crate name spelling against crates.io in a browser.","Search first with `crates search <term>` to find the exact crate name, then re-run `crates crate <name>`.","Retry later if crates.io is degraded; the empty body may be transient.","Catch EmptyResultError in your tooling and show a 'not found' message instead of crashing."],"exampleFix":"// before\nconst info = await cli.crates.crate({ name: 'tokyio' });\n// after\nconst info = await cli.crates.crate({ name: 'tokio' }); // or search first:\nconst hits = await cli.crates.search({ query: 'tokio' });","handlingStrategy":"try-catch","validationCode":"if (!/^[A-Za-z][A-Za-z0-9_-]{0,63}$/.test(name ?? '')) {\n  throw new Error(`\"${name}\" does not look like a crates.io crate name`);\n}","typeGuard":"function isPlausibleCrateName(v) {\n  return typeof v === 'string' && /^[A-Za-z][A-Za-z0-9_-]{0,63}$/.test(v.trim());\n}","tryCatchPattern":"try {\n  const info = await cli.crates.crate({ name });\n} catch (e) {\n  if (e instanceof EmptyResultError) {\n    console.warn(`Crate \"${name}\" not found on crates.io; try 'crates search'.`);\n    return null;\n  }\n  throw e;\n}","preventionTips":["Verify the name exists on crates.io before scripting around it.","Run `crates search` first when the name is uncertain.","Treat EmptyResultError as 'not found', not as an infrastructure failure.","Remember yanked/removed crates may return no metadata."],"tags":["empty-result","crates-io","not-found"],"backgroundTag":"empty-result-set","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}