{"record":{"id":"4b512a8a9a40f972","repo":"koala73/worldmonitor","slug":"global-fetch-is-unavailable-node-18-is-required","errorCode":null,"errorMessage":"global fetch is unavailable — Node 18+ is required","messagePattern":"global fetch is unavailable — Node 18\\+ is required","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/src/run.mjs","lineNumber":76,"sourceCode":"  const env = io.env || (typeof process !== 'undefined' ? process.env : {});\n  const stdout = io.stdout || ((s) => process.stdout.write(s));\n  const stderr = io.stderr || ((s) => process.stderr.write(s));\n\n  const parsed = parseArgs(argv);\n  const { command, options } = parsed;\n\n  if (options.version) {\n    stdout(`${VERSION}\\n`);\n    return 0;\n  }\n  if (options.help || !command || command === 'help') {\n    stdout(`${HELP}\\n`);\n    return 0;\n  }\n\n  try {\n    if (!fetchImpl) {\n      throw new Error('global fetch is unavailable — Node 18+ is required');\n    }\n\n    const config = resolveConfig(env);\n    const plan = planRequest(parsed, config);\n\n    if (plan.kind === 'list') {\n      const specUrl = plan.specUrl || DEFAULT_SPEC_URL;\n      const headers = { 'user-agent': USER_AGENT, accept: 'application/json' };\n      const apiKey = options.apiKey || config.apiKey;\n      if (apiKey) headers[API_KEY_HEADER] = apiKey;\n      const res = await withTimeout(options.timeout, (signal) =>\n        fetchImpl(specUrl, { headers, signal }),\n      );\n      const spec = parseBody(await res.text(), res.headers);\n      if (!res.ok) {\n        stderr(`${formatOutput(spec, options)}\\n`);\n        if (res.status === 401) stderr(`${AUTH_HINT}\\n`);\n        return 1;","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/koala73/worldmonitor/blob/eeab0a219fce0f02a00603b532dbae9041b934ac/cli/src/run.mjs#L58-L94","documentation":"cli/src/run.mjs resolves its HTTP client as io.fetch || globalThis.fetch. Node releases before 18 have no global fetch (undici landed in Node 18), so run() aborts with this error before attempting any request; the generic catch maps it to exit code 1. The repository standardizes on Node 24 via .nvmrc.","triggerScenarios":"Executing the CLI under Node 16/14/10 (system node, stale nvm alias, CI image, Docker base); embedding run() without injecting io.fetch; exotic runtimes that lack a global fetch implementation.","commonSituations":"Dev machine defaulting to an old LTS via nvm; CI base image (node:16) never updated; tool managers shimming an old Node; calling run() from a test harness that forgets the fetch injection.","solutions":["Check node --version and upgrade to Node 18+ — ideally Node 24 per the repo's .nvmrc (nvm use)","In CI, switch the base image to node:20+ or node:24","When embedding run() programmatically, inject a client: run(argv, { fetch: myFetch })","If a polyfill is unavoidable in the short term, set globalThis.fetch = require('undici').fetch before importing the CLI"],"exampleFix":"# before\n$ node --version\nv16.20.2\n$ worldmonitor tools\n# Error: global fetch is unavailable — Node 18+ is required\n\n# after\n$ nvm use          # picks up .nvmrc (Node 24)\nv24.x.x\n$ worldmonitor tools","handlingStrategy":"validation","validationCode":"// Fail fast with a clear message before any CLI work\nif (typeof globalThis.fetch !== 'function') {\n  console.error('Node 18+ required (global fetch missing). Current:', process.version);\n  process.exit(1);\n}","typeGuard":"type FetchLike = typeof globalThis.fetch;\nfunction hasGlobalFetch(): fetch is FetchLike {\n  return typeof globalThis.fetch === 'function';\n}","tryCatchPattern":null,"preventionTips":["Run `node --version` in shell profiles/CI before invoking the CLI","Use the repository's .nvmrc (Node 24) in dev and CI","When embedding run(), always inject io.fetch so tests and old runtimes stay hermetic"],"tags":["node","runtime-version","cli","environment"],"backgroundTag":"missing-global-fetch","analyzedSha":"eeab0a219fce0f02a00603b532dbae9041b934ac","analyzedAt":"2026-08-21T16:51:25.751Z","schemaVersion":2},"datasetVersion":"2026-08-23T16:17:53.355Z"}