affaan-m/ECC · error

Failed to read

Error message

Failed to read ${label}: ${error.message}

What it means

readJson wraps fs.readFileSync + JSON.parse for manifest files (modules, profiles, components). Any read or parse failure — missing file, permissions, invalid JSON — is rethrown with the human-readable label in the message.

Solutions

  1. Check the labeled file exists at the expected path relative to the project root
  2. Validate the JSON parses (e.g. `node -e "JSON.parse(require('fs').readFileSync(path,'utf8'))"`) and fix syntax errors
  3. Pass the correct projectRoot/homeDir options so manifests are resolved from the right directory
  4. Fix file permissions or restore the manifest from the repo

Example fix

// before
loadInstallManifests({ projectRoot: '/wrong/path' });
// after
const fs = require('fs');
const p = '/repo/scripts/install-manifests/modules.json';
if (!fs.existsSync(p)) throw new Error('restore manifests from repo');
loadInstallManifests({ projectRoot: '/repo' });
Defensive patterns

Strategy: try-catch

Validate before calling

const fs = require('fs');
function manifestReadable(p) { try { JSON.parse(fs.readFileSync(p, 'utf8')); return true; } catch { return false; } }

Try / catch

try { loadInstallManifests(opts); } catch (e) { if (String(e.message).startsWith('Failed to read')) { console.error('Check manifest path/JSON for:', e.message); process.exitCode = 1; } else throw e; }

Prevention

When it happens

Trigger: Calling loadInstallManifests (via modulesData/profilesData/componentsData) when a manifest JSON file is absent, unreadable, or contains malformed JSON.

Common situations: Incomplete checkout or install missing manifest files; wrong repoRoot/projectRoot option pointing at the wrong directory; JSON syntax error after hand-editing a manifest; restrictive file permissions.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/48e3b1e085270be8. Report an issue: GitHub.

Appendix: source

Thrown at scripts/lib/install-manifests.js:172

});
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 8321021c54)