jackwener/OpenCLI · error · ArgumentError

openalex work id "${value}" must be a Work (W…) ID, got "${i

Error message

openalex work id "${value}" must be a Work (W…) ID, got "${id[0]}…"

What it means

When requireWorkRef is given a full openalex.org or api.openalex.org URL, it extracts the entity ID and requires it to be a Work (W…) ID; any other entity type (A authors, S sources, I institutions, etc.) throws this ArgumentError. The library only supports work lookups, so a valid but wrong-kind OpenAlex ID is rejected with both the original input and the offending prefix in the message.

Source

Thrown at clis/openalex/utils.js:53

    return n;
}

/**
 * Resolve a user-supplied work identifier to OpenAlex's canonical path
 * segment. Accepts `W…` IDs, `doi:10.…`, raw DOIs, or full
 * `https://doi.org/…` / `https://openalex.org/W…` URLs.
 */
export function requireWorkRef(value) {
    const raw = String(value ?? '').trim();
    if (!raw) {
        throw new ArgumentError('openalex work id is required (e.g. "W2741809807", "10.7717/peerj.4375")');
    }
    // 1) full openalex URL
    const oaUrl = raw.match(/^https?:\/\/(?:api\.)?openalex\.org\/(?:works\/)?([WAaSCFwIPwT]\d+)/i);
    if (oaUrl) {
        const id = oaUrl[1].toUpperCase();
        if (id[0] !== 'W') {
            throw new ArgumentError(`openalex work id "${value}" must be a Work (W…) ID, got "${id[0]}…"`);
        }
        return id;
    }
    // 2) bare W… id
    if (WORK_ID.test(raw.toUpperCase())) {
        return raw.toUpperCase();
    }
    // 3) doi:… prefix
    if (/^doi:/i.test(raw)) {
        const doi = raw.replace(/^doi:/i, '').trim();
        if (DOI_BARE.test(doi)) return `doi:${doi}`;
    }
    // 4) full doi URL
    const doiUrl = raw.match(/^https?:\/\/(?:dx\.)?doi\.org\/(.+)$/i);
    if (doiUrl && DOI_BARE.test(doiUrl[1])) {
        return `doi:${doiUrl[1]}`;
    }
    // 5) bare 10.xxxx/yyy DOI

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Use the W… ID of the work itself (from the work's OpenAlex page URL) or its DOI
  2. If you actually have an author/source, use the corresponding authors/sources command instead of the work endpoint
  3. Strip to the W-id portion or replace the URL with the DOI link from the work's page

Example fix

// before
await work('https://openalex.org/A5023888391'); // author URL
// after
await work('https://openalex.org/W2741809807'); // work URL (or '10.7717/peerj.4375')
Defensive patterns

Strategy: validation

Validate before calling

function extractWorkIdFromUrl(url) {
  const m = String(url).match(/openalex\.org\/(?:works\/)?([A-Z]\d+)/i);
  if (!m) return null;
  const id = m[1].toUpperCase();
  if (id[0] !== 'W') throw new Error(`URL is an ${id[0]}-entity, need a W (work) URL`);
  return id;
}

Type guard

function isWorkId(id) {
  return typeof id === 'string' && /^W\d{4,}$/.test(id.trim().toUpperCase());
}

Try / catch

try {
  await work(ref);
} catch (e) {
  if (e.name === 'ArgumentError' && e.message.includes('must be a Work')) {
    console.error('That OpenAlex URL is not a work; use the W… id or the DOI'); process.exitCode = 2;
  } else throw e;
}

Prevention

When it happens

Trigger: Passing a URL like https://openalex.org/A5088555860 (author) or https://openalex.org/S123456 (source) — the regex matches the ID but the first character is not 'W'.

Common situations: Copying a link from an OpenAlex author or institution page instead of the work page; confusing OpenAlex IDs with DOI-based lookups; mixing up entity types when scripting over OpenAlex pages.

Related errors


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