{"record":{"id":"48e3b1e085270be8","repo":"affaan-m/ECC","slug":"failed-to-read-label-error-message","errorCode":null,"errorMessage":"Failed to read ${label}: ${error.message}","messagePattern":"Failed to read (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/install-manifests.js","lineNumber":152,"sourceCode":"});\nconst TARGET_DEFAULT_PROFILE_IDS = Object.freeze({\n  opencode: 'opencode',\n});\nconst TARGET_DEFAULT_EXCLUSIONS = Object.freeze({\n  opencode: [\n    {\n      moduleId: 'hooks-runtime',\n      reason: 'OpenCode defaults intentionally exclude hooks-runtime until users opt in.',\n      optInCommand: './install.sh --target opencode --modules hooks-runtime',\n    },\n  ],\n});\n\nfunction readJson(filePath, label) {\n  try {\n    return JSON.parse(fs.readFileSync(filePath, 'utf8'));\n  } catch (error) {\n    throw new Error(`Failed to read ${label}: ${error.message}`);\n  }\n}\n\nfunction dedupeStrings(values) {\n  return [...new Set((Array.isArray(values) ? values : []).map(value => String(value).trim()).filter(Boolean))];\n}\n\nfunction listSkillDirectoryIds(repoRoot) {\n  const skillsRoot = path.join(repoRoot, 'skills');\n  if (!fs.existsSync(skillsRoot) || !fs.statSync(skillsRoot).isDirectory()) {\n    return [];\n  }\n\n  return fs.readdirSync(skillsRoot, { withFileTypes: true })\n    .filter(entry => entry.isDirectory())\n    .map(entry => entry.name)\n    .sort();\n}","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/install-manifests.js#L134-L170","documentation":"readJson wraps fs.readFileSync + JSON.parse for the manifest files (install-modules.json, install-profiles.json, install-components.json). Any filesystem error (missing file, permission denied) or JSON syntax error is rethrown with the caller-supplied label prefixed, so the caller knows which manifest failed.","triggerScenarios":"loadInstallManifests or any manifest reader calling readJson when the manifest file does not exist at the expected path, is not readable, or contains malformed JSON. The label in the message identifies which of the three manifest files failed.","commonSituations":"Running the installer from a shallow clone that excluded manifests/; manifests/ files were deleted or git-ignored; hand-edited manifest introduced a JSON syntax error; permission/ownership issue on the manifest file; running installer from the wrong working directory so DEFAULT_REPO_ROOT resolves wrong.","solutions":["Open the manifest named by `${label}` and locate the JSON error (line/column from the underlying error message).","Restore the file from git: `git checkout HEAD -- manifests/<file>.json`.","Run the installer from the repository root so DEFAULT_REPO_ROOT (__dirname/../..) points at manifests/.","Fix filesystem permissions: `chmod -R u+rw manifests/`."],"exampleFix":"// before: manifests/install-modules.json has a trailing comma → parse fails\n// after: validate then restore\nnode -e 'JSON.parse(require(\"fs\").readFileSync(\"manifests/install-modules.json\",\"utf8\"))'\ngit checkout HEAD -- manifests/install-modules.json","handlingStrategy":"try-catch","validationCode":"const fs = require('fs');\nfunction manifestsAreReadable(repoRoot) {\n  for (const name of ['install-modules.json', 'install-profiles.json', 'install-components.json']) {\n    const p = `${repoRoot}/manifests/${name}`;\n    if (!fs.existsSync(p)) continue; // components optional\n    JSON.parse(fs.readFileSync(p, 'utf8'));\n  }\n  return true;\n}\n// before invoking installer: manifestsAreReadable(repoRoot)","typeGuard":"function isParsableJsonFile(filePath) {\n  try { JSON.parse(fs.readFileSync(filePath, 'utf8')); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  return readJson(filePath, label);\n} catch (err) {\n  if (err.message.startsWith(`Failed to read ${label}`)) {\n    // restore the manifest from git or fail gracefully\n  } else throw err;\n}","preventionTips":["Validate manifests/ JSON in CI (e.g. `npm run catalog:sync` + `npm test`).","Never hand-edit manifests without re-running the validator.","Ensure manifests/ ships in tarballs and clones.","Run the installer from the real repository root."],"tags":["manifest","json","filesystem","install"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}