{"record":{"id":"f0f8021a1e9bb354","repo":"jackwener/OpenCLI","slug":"openalex-work-id-is-required-e-g-w2741809807","errorCode":null,"errorMessage":"openalex work id is required (e.g. \"W2741809807\", \"10.7717/peerj.4375\")","messagePattern":"openalex work id is required \\(e\\.g\\. \"W2741809807\", \"10\\.7717/peerj\\.4375\"\\)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/openalex/utils.js","lineNumber":46,"sourceCode":"    const n = typeof raw === 'number' ? raw : Number(raw);\n    if (!Number.isInteger(n) || n <= 0) {\n        throw new ArgumentError(`openalex ${label} must be a positive integer`);\n    }\n    if (n > maxValue) {\n        throw new ArgumentError(`openalex ${label} must be <= ${maxValue}`);\n    }\n    return n;\n}\n\n/**\n * Resolve a user-supplied work identifier to OpenAlex's canonical path\n * segment. Accepts `W…` IDs, `doi:10.…`, raw DOIs, or full\n * `https://doi.org/…` / `https://openalex.org/W…` URLs.\n */\nexport function requireWorkRef(value) {\n    const raw = String(value ?? '').trim();\n    if (!raw) {\n        throw new ArgumentError('openalex work id is required (e.g. \"W2741809807\", \"10.7717/peerj.4375\")');\n    }\n    // 1) full openalex URL\n    const oaUrl = raw.match(/^https?:\\/\\/(?:api\\.)?openalex\\.org\\/(?:works\\/)?([WAaSCFwIPwT]\\d+)/i);\n    if (oaUrl) {\n        const id = oaUrl[1].toUpperCase();\n        if (id[0] !== 'W') {\n            throw new ArgumentError(`openalex work id \"${value}\" must be a Work (W…) ID, got \"${id[0]}…\"`);\n        }\n        return id;\n    }\n    // 2) bare W… id\n    if (WORK_ID.test(raw.toUpperCase())) {\n        return raw.toUpperCase();\n    }\n    // 3) doi:… prefix\n    if (/^doi:/i.test(raw)) {\n        const doi = raw.replace(/^doi:/i, '').trim();\n        if (DOI_BARE.test(doi)) return `doi:${doi}`;","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/openalex/utils.js#L28-L64","documentation":"requireWorkRef resolves a user-supplied work identifier (W-id, DOI, or URL) and throws ArgumentError when the input is empty or whitespace-only. The message reminds callers of the accepted formats: a Work id like W2741809807 or a DOI like 10.7717/peerj.4375. Unlike requireString this is ref-specific because the resolved value is used to build an OpenAlex works path.","triggerScenarios":"Calling a work-lookup command (ref/get) with an empty or whitespace-only `ref` argument — null/undefined coerce to '' via String(value ?? '').trim().","commonSituations":"Shell variable holding the paper ID is unset; CLI positional argument omitted; a pipeline step upstream produced an empty ID because a prior search returned nothing.","solutions":["Supply a valid work reference: a W-id, a bare DOI, a doi.org URL, or an openalex.org URL","Check that the variable feeding the ref is actually set and non-empty","If the ref came from a prior search, verify that search returned a result before chaining"],"exampleFix":"// before\nconst id = process.env.WORK_ID; // unset\nawait work(id);\n// after\nconst id = process.env.WORK_ID;\nif (!id?.trim()) { console.error('WORK_ID must be set, e.g. W2741809807'); process.exit(1); }\nawait work(id);","handlingStrategy":"validation","validationCode":"function assertWorkRef(ref) {\n  if (!String(ref ?? '').trim()) {\n    throw new Error('work ref is required (W-id or DOI)');\n  }\n}","typeGuard":"function hasWorkRef(v) {\n  return typeof v === 'string' && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  await work(ref);\n} catch (e) {\n  if (e.name === 'ArgumentError' && e.message.includes('is required')) {\n    console.error('Provide a W-id or DOI, e.g. W2741809807'); process.exitCode = 2;\n  } else throw e;\n}","preventionTips":["Check env/config variables are set before invoking work lookups","When chaining search -> work, verify the search returned a hit first","Use `ref?.trim()` guards in scripts"],"tags":["openalex","argument-validation","missing-identifier"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}