affaan-m/ECC · error · Error

Invalid canonical install-state: required projection fields…

Error message

Invalid canonical install-state: required projection fields are missing

What it means

buildInstallStateStoreRecord projects a canonical install-state into a storage record, but first requires the state object to carry all four mandatory sections: target, request, resolution, and source. If any of them is missing (or state itself is null/undefined), the projection is considered invalid and this error is thrown. It signals a corrupt or truncated install-state rather than a bad individual field value.

Solutions

  1. Log/inspect the state object and ensure target, request, resolution, and source are all present before calling
  2. Rebuild the install-state through the library's canonical creation path instead of hand-assembling it
  3. If data came from disk, validate it against the expected schema and re-run the install to regenerate the state
  4. After an upgrade, migrate old states to the new shape before projecting

Example fix

// before
buildInstallStateStoreRecord({ target, request }); // missing resolution & source
// after
buildInstallStateStoreRecord({ target, request, resolution, source });
Defensive patterns

Strategy: validation

Validate before calling

const REQUIRED = ['target', 'request', 'resolution', 'source'];
const missing = REQUIRED.filter(k => !state?.[k]);
if (missing.length) {
  throw new Error(`install-state missing sections: ${missing.join(', ')}`);
}

Type guard

function isCompleteInstallState(s) {
  return Boolean(s && s.target && s.request && s.resolution && s.source);
}

Try / catch

try {
  const record = buildInstallStateStoreRecord(state);
} catch (err) {
  if (err.message.startsWith('Invalid canonical install-state')) {
    console.error('State object incomplete — regenerate via canonical install flow');
    state = regenerateInstallState();
    return buildInstallStateStoreRecord(state);
  } throw err;
}

Prevention

When it happens

Trigger: Calling buildInstallStateStoreRecord with null/undefined, or with a state object built by an older/different version missing e.g. resolution or source; destructuring an incomplete record loaded from disk and passing the fragment in; a partial object literal in tests.

Common situations: Schema drift after a library upgrade renamed or removed one of the sections; a migration that copied only part of the state; hand-constructed fixtures missing optional-looking sections that are actually required; loading a JSON file that was truncated by a crashed write.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at scripts/lib/state-store/install-state-projection.js:21

const path = require('path');

const MANAGED_FILE_HEALTH_CODES = new Set([
  'missing-target-root',
  'unsafe-managed-destination',
  'unsafe-repair-source',
  'missing-managed-files',
  'drifted-managed-files',
  'missing-source-files',
  'unverified-managed-operations',
]);

function cloneJsonValue(value) {
  return value === undefined ? undefined : JSON.parse(JSON.stringify(value));
}

function buildInstallStateStoreRecord(state) {
  if (!state || !state.target || !state.request || !state.resolution || !state.source) {
    throw new Error('Invalid canonical install-state: required projection fields are missing');
  }

  return {
    targetId: state.target.id,
    targetRoot: state.target.root,
    profile: state.request.profile ?? null,
    modules: Array.isArray(state.resolution.selectedModules)
      ? [...state.resolution.selectedModules]
      : [],
    operations: Array.isArray(state.operations)
      ? state.operations.map(operation => cloneJsonValue(operation))
      : [],
    installedAt: state.installedAt,
    sourceVersion: state.source.repoVersion ?? null,
  };
}

function warningFor(record, code, message) {

View on GitHub (pinned to 8321021c54)