affaan-m/ECC · error · Error

Invalid install-state${label ? ` (${label})` : ''}: ${format

Error message

Invalid install-state${label ? ` (${label})` : ''}: ${formatValidationErrors(result.errors)}

What it means

Thrown by assertValidInstallState() when the hand-rolled validator (createFallbackValidator) returns errors against the ecc.install.v1 schema. The validator enforces required fields, no additional properties, and primitive types — mirroring schemas/install-state.schema.json. The message lists every AJAX-style instancePath/message pair via formatValidationErrors.

Source

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

function formatValidationErrors(errors = []) {
  return errors
    .map(error => `${error.instancePath || '/'} ${error.message}`)
    .join('; ');
}

function validateInstallState(state) {
  const validator = getValidator();
  const valid = validator(state);
  return {
    valid,
    errors: validator.errors || [],
  };
}

function assertValidInstallState(state, label) {
  const result = validateInstallState(state);
  if (!result.valid) {
    throw new Error(`Invalid install-state${label ? ` (${label})` : ''}: ${formatValidationErrors(result.errors)}`);
  }
}

function createInstallState(options) {
  const installedAt = options.installedAt || new Date().toISOString();
  const state = {
    schemaVersion: 'ecc.install.v1',
    installedAt,
    target: {
      id: options.adapter.id,
      target: options.adapter.target || undefined,
      kind: options.adapter.kind || undefined,
      root: options.targetRoot,
      installStatePath: options.installStatePath,
    },
    request: {
      profile: options.request.profile || null,
      modules: Array.isArray(options.request.modules) ? [...options.request.modules] : [],

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Read the full validation error list — each entry's instancePath points at the offending field.
  2. Delete the file and rerun the installer to regenerate a schema-conformant state.
  3. If migrating, write a small transform that adds/removes keys to match ecc.install.v1.
  4. Compare against createInstallState() output in install-state.js:236 for the canonical shape.

Example fix

// before — state file missing request field
{ "schemaVersion": "ecc.install.v1", "target": {}, "resolution": {}, "source": {}, "operations": [] }
// after
{
  "schemaVersion": "ecc.install.v1",
  "installedAt": "2025-01-01T00:00:00.000Z",
  "target": { "id": "claude", "root": "/" },
  "request": { "profile": "baseline", "modules": [], "includeComponents": [], "excludeComponents": [], "legacyLanguages": [], "legacyMode": false },
  "resolution": { "selectedModules": [], "skippedModules": [] },
  "source": { "repoVersion": null, "repoCommit": null, "manifestVersion": null },
  "operations": []
}
Defensive patterns

Strategy: validation

Validate before calling

const { validateInstallState } = require('./scripts/lib/install-state');
const result = validateInstallState(state);
if (!result.valid) {
  // either migrate or discard
  console.error(result.errors);
  return null;
}
// safe to use state

Try / catch

try {
  assertValidInstallState(state, label);
} catch (err) {
  if (/^Invalid install-state/.test(err.message)) {
    // discard and let the installer regenerate
    fs.rmSync(statePath, { force: true });
    state = null;
  } else throw err;
}

Prevention

When it happens

Trigger: An install-state file that is missing schemaVersion, target, request, resolution, source, or operations; has extra top-level keys; has wrong-typed fields (e.g. installedAt is a number); was written by an older/newer ECC version with a different schema.

Common situations: Cross-version migration: an older ECC wrote a state file the new validator rejects; a fork hand-edited the JSON; a third-party tool produced a near-miss file.

Related errors


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