affaan-m/ECC · error · Error
Failed to read ${label}: ${error.message}
Error message
Failed to read ${label}: ${error.message} What it means
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.
Source
Thrown at scripts/lib/install-manifests.js:152
});
const TARGET_DEFAULT_PROFILE_IDS = Object.freeze({
opencode: 'opencode',
});
const TARGET_DEFAULT_EXCLUSIONS = Object.freeze({
opencode: [
{
moduleId: 'hooks-runtime',
reason: 'OpenCode defaults intentionally exclude hooks-runtime until users opt in.',
optInCommand: './install.sh --target opencode --modules hooks-runtime',
},
],
});
function readJson(filePath, label) {
try {
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
} catch (error) {
throw new Error(`Failed to read ${label}: ${error.message}`);
}
}
function dedupeStrings(values) {
return [...new Set((Array.isArray(values) ? values : []).map(value => String(value).trim()).filter(Boolean))];
}
function listSkillDirectoryIds(repoRoot) {
const skillsRoot = path.join(repoRoot, 'skills');
if (!fs.existsSync(skillsRoot) || !fs.statSync(skillsRoot).isDirectory()) {
return [];
}
return fs.readdirSync(skillsRoot, { withFileTypes: true })
.filter(entry => entry.isDirectory())
.map(entry => entry.name)
.sort();
}View on GitHub (pinned to 01e15490f0)
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/`.
Example fix
// before: manifests/install-modules.json has a trailing comma → parse fails
// after: validate then restore
node -e 'JSON.parse(require("fs").readFileSync("manifests/install-modules.json","utf8"))'
git checkout HEAD -- manifests/install-modules.json Defensive patterns
Strategy: try-catch
Validate before calling
const fs = require('fs');
function manifestsAreReadable(repoRoot) {
for (const name of ['install-modules.json', 'install-profiles.json', 'install-components.json']) {
const p = `${repoRoot}/manifests/${name}`;
if (!fs.existsSync(p)) continue; // components optional
JSON.parse(fs.readFileSync(p, 'utf8'));
}
return true;
}
// before invoking installer: manifestsAreReadable(repoRoot) Type guard
function isParsableJsonFile(filePath) {
try { JSON.parse(fs.readFileSync(filePath, 'utf8')); return true; } catch { return false; }
} Try / catch
try {
return readJson(filePath, label);
} catch (err) {
if (err.message.startsWith(`Failed to read ${label}`)) {
// restore the manifest from git or fail gracefully
} else throw err;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Failed to parse ${label} at ${filePath}: ${error.message}
- Invalid ${label} at ${filePath}: expected a JSON object
- Install manifests not found under ${repoRoot}
- Invalid ${label}: ${error.message}
- Invalid ${label}: expected JSON-compatible data
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/48e3b1e085270be8.
Report an issue: GitHub.