affaan-m/ECC · error · Error

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

Error message

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

What it means

Thrown by readJson() in install-state.js when either fs.readFileSync throws (file missing, permission denied) or JSON.parse throws (malformed JSON). The label argument identifies which file was being read so the message is actionable. install-state.js is intentionally dependency-free, so the error wraps the underlying node error message verbatim.

Source

Thrown at scripts/lib/install-state.js:24

// bytes must be the installed bytes). install-state is validated by the
// hand-rolled validator below, which enforces the same constraints as
// schemas/install-state.schema.json (ecc.install.v1).

let cachedValidator = null;

function cloneJsonValue(value) {
  if (value === undefined) {
    return undefined;
  }

  return JSON.parse(JSON.stringify(value));
}

function readJson(filePath, label) {
  try {
    return JSON.parse(fs.readFileSync(filePath, 'utf8'));
  } catch (error) {
    throw new Error(`Failed to read ${label}: ${error.message}`);
  }
}

function getValidator() {
  if (cachedValidator) {
    return cachedValidator;
  }

  cachedValidator = createFallbackValidator();
  return cachedValidator;
}

function createFallbackValidator() {
  const validate = state => {
    const errors = [];
    validate.errors = errors;

    function pushError(instancePath, message) {

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Check whether the path exists with fs.existsSync before reading; treat absence as 'not installed'.
  2. If the file is corrupt, delete it and let the installer recreate it on next run.
  3. Verify read permissions on the parent directory (ls -la).
  4. Ensure no other tool writes to ecc-install-state.json with a different schema.

Example fix

// before
const state = readJson(statePath, 'install-state');
// after
if (!fs.existsSync(statePath)) return null;
let state;
try { state = readJson(statePath, 'install-state'); }
catch (e) {
  fs.rmSync(statePath, { force: true }); // corrupt — let installer rewrite
  return null;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!fs.existsSync(filePath)) {
  return null; // no prior state — fresh install
}
const stat = fs.statSync(filePath);
if (!stat.isFile()) {
  throw new Error(`${filePath} is not a regular file`);
}
// proceed to readJson

Try / catch

try {
  return readJson(filePath, label);
} catch (err) {
  if (/Failed to read/.test(err.message)) {
    // corrupt or unreadable — back up and reset
    fs.rmSync(filePath, { force: true });
    return null;
  }
  throw err;
}

Prevention

When it happens

Trigger: Reading the install-state file (ecc-install-state.json) before it was ever written; reading after a partial write corrupted the JSON; insufficient filesystem permissions; the path resolved to a directory.

Common situations: First run after install before any state exists; a concurrent process truncated the file; an OS crash mid-write left invalid JSON; permissions changed under .claude/ or .cursor/.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/ae2106a2161df953. Report an issue: GitHub.