{"record":{"id":"b7c57aa1c4278569","repo":"affaan-m/ECC","slug":"failed-to-read-normalizepath-path-relative-root","errorCode":null,"errorMessage":"Failed to read ${normalizePath(path.relative(ROOT, outputPath))}: ${error.message}","messagePattern":"Failed to read (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/ci/generate-command-registry.js","lineNumber":223,"sourceCode":"}\n\nfunction formatRegistry(registry) {\n  return `${JSON.stringify(registry, null, 2)}\\n`;\n}\n\nfunction writeRegistry(registry, outputPath = DEFAULT_OUTPUT_PATH) {\n  fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n  fs.writeFileSync(outputPath, formatRegistry(registry), 'utf8');\n}\n\nfunction checkRegistry(registry, outputPath = DEFAULT_OUTPUT_PATH) {\n  const expected = formatRegistry(registry);\n  let current;\n\n  try {\n    current = fs.readFileSync(outputPath, 'utf8');\n  } catch (error) {\n    throw new Error(`Failed to read ${normalizePath(path.relative(ROOT, outputPath))}: ${error.message}`);\n  }\n\n  if (current !== expected) {\n    throw new Error(`${normalizePath(path.relative(ROOT, outputPath))} is out of date; run npm run command-registry:write`);\n  }\n}\n\nfunction formatTextSummary(registry) {\n  const lines = [\n    'Command registry statistics',\n    '',\n    `Total commands: ${registry.totalCommands}`,\n    '',\n    'By type:',\n  ];\n\n  for (const [type, count] of Object.entries(registry.statistics.byType)) {\n    lines.push(`  ${type}: ${count}`);","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/ci/generate-command-registry.js#L205-L241","documentation":"`checkRegistry` (invoked by `generate-command-registry.js --check`) reads `docs/COMMAND-REGISTRY.json` from disk via `fs.readFileSync` and compares it to a freshly-generated registry. If the read itself fails (file does not exist, permission denied, path is a directory), the throw `Failed to read docs/COMMAND-REGISTRY.json: <error.message>` fires. This is a missing/unreadable-artifact error, not a staleness error.","triggerScenarios":"Triggered by `node scripts/ci/generate-command-registry.js --check` (or `npm run command-registry:check`) when docs/COMMAND-REGISTRY.json does not exist (never generated), was deleted, is outside the read path, or has restrictive permissions. The check mode requires the file to pre-exist.","commonSituations":"A fresh clone runs CI before the registry has been generated. The file was gitignored or removed in a cleanup. Permissions were tightened. The docs/ directory was deleted. CI runs --check without a preceding --write step.","solutions":["Generate the registry first: `node scripts/ci/generate-command-registry.js --write` (or `npm run command-registry:write`).","Commit docs/COMMAND-REGISTRY.json to the repo so --check can read it in CI.","Verify the file path matches DEFAULT_OUTPUT_PATH (docs/COMMAND-REGISTRY.json) and is readable.","In CI, either run --write before --check, or ensure the committed artifact is present."],"exampleFix":"// before — CI runs check on a fresh clone with no committed registry\nnode scripts/ci/generate-command-registry.js --check\n// -> Failed to read docs/COMMAND-REGISTRY.json: ENOENT\n\n// after — generate once, commit, then check\nnode scripts/ci/generate-command-registry.js --write\ngit add docs/COMMAND-REGISTRY.json\ngit commit -m \"chore: add command registry\"\n// CI now passes --check","handlingStrategy":"try-catch","validationCode":"const fs = require('fs');\nconst path = require('path');\nconst regPath = path.join('docs', 'COMMAND-REGISTRY.json');\nif (!fs.existsSync(regPath)) {\n  console.error(`${regPath} does not exist. Generate it first:`);\n  console.error('  node scripts/ci/generate-command-registry.js --write');\n  process.exit(1);\n}\ntry { fs.accessSync(regPath, fs.constants.R_OK); }\ncatch { console.error(`${regPath} is not readable`); process.exit(1); }","typeGuard":"function registryReadable(outputPath) {\n  try { fs.accessSync(outputPath, fs.constants.R_OK); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  run(['--check']);\n} catch (error) {\n  if (/Failed to read.*COMMAND-REGISTRY\\.json/i.test(error.message)) {\n    console.error('Registry artifact missing. Run: node scripts/ci/generate-command-registry.js --write');\n  }\n  throw error;\n}","preventionTips":["Always commit docs/COMMAND-REGISTRY.json after generating it — `--check` requires it to exist.","In CI, run `--write` once (or ensure the committed artifact is present) before `--check`.","Do not gitignore docs/COMMAND-REGISTRY.json.","Add a pre-commit hook that runs `--write` when commands/ changes."],"tags":["ci","command-registry","filesystem","artifact-missing","enoent"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}