affaan-m/ECC · error · Error

Harness capability catalog is out of sync with install targe

Error message

Harness capability catalog is out of sync with install targets

What it means

The second require-time catalog validation: the sorted set of all catalogued target ids must deep-equal both SUPPORTED_INSTALL_TARGETS (the supported list in install-manifests.js) and the registered install-target adapters. Any target that is supported/registered but missing from the catalog — or catalogued but not registered — throws at module load, keeping the three sources of truth locked together.

Source

Thrown at scripts/lib/harness-capabilities.js:274

}

function validateCatalog() {
  const adapters = listInstallTargetAdapters();
  const adapterByTarget = new Map(adapters.map(adapter => [adapter.target, adapter]));
  const catalogTargetIds = HARNESS_CAPABILITIES.flatMap(harness => harness.targetIds);

  if (new Set(catalogTargetIds).size !== catalogTargetIds.length) {
    throw new Error('Harness capability catalog contains duplicate install target ids');
  }

  const supported = [...SUPPORTED_INSTALL_TARGETS].sort();
  const registered = adapters.map(adapter => adapter.target).sort();
  const catalogued = [...catalogTargetIds].sort();
  if (
    JSON.stringify(catalogued) !== JSON.stringify(supported)
    || JSON.stringify(catalogued) !== JSON.stringify(registered)
  ) {
    throw new Error('Harness capability catalog is out of sync with install targets');
  }

  for (const harness of HARNESS_CAPABILITIES) {
    for (const declaredScope of harness.scopes) {
      const adapter = adapterByTarget.get(declaredScope.targetId);
      if (!adapter || expectedRootForAdapter(adapter) !== declaredScope.root) {
        throw new Error(
          `Harness capability root is out of sync for target ${declaredScope.targetId}`
        );
      }
    }
  }
}

validateCatalog();

function listHarnessCapabilities() {
  return HARNESS_CAPABILITIES.slice();

View on GitHub (pinned to d8409a4b08)

Solutions

  1. Diff the three lists: SUPPORTED_INSTALL_TARGETS, adapters.map(a => a.target), and the union of harness.targetIds — the message fires when sorted unions differ
  2. Update all three in the same commit: register the adapter, add the id to SUPPORTED_INSTALL_TARGETS, and list it in exactly one harness's targetIds
  3. Verify with `node -e "require('./scripts/lib/harness-capabilities.js')"`
  4. Run the repo's install-surface tests (npm test) which exercise catalog/adapter consistency

Example fix

// before: adapter 'zed' registered + supported, but no harness lists it
// after
{ id: 'editors', targetIds: ['zed', 'cursor'] },
Defensive patterns

Strategy: validation

Validate before calling

// CI guard: catalog, supported list, and adapters must match exactly
const { HARNESS_CAPABILITIES } = require('./scripts/lib/harness-capabilities.js');
const { SUPPORTED_INSTALL_TARGETS } = require('./scripts/lib/install-manifests.js');
const catalogued = [...new Set(HARNESS_CAPABILITIES.flatMap(h => h.targetIds))].sort();
const supported = [...SUPPORTED_INSTALL_TARGETS].sort();
if (JSON.stringify(catalogued) !== JSON.stringify(supported)) {
  throw new Error(`Drift: catalog=${catalogued} vs supported=${supported}`);
}

Prevention

When it happens

Trigger: Adding a new install target: the adapter file is created and SUPPORTED_INSTALL_TARGETS updated, but no harness entry lists the new targetId. Or the reverse: a targetId is catalogued while its adapter isn't registered (e.g. the adapter module isn't imported by listInstallTargetAdapters).

Common situations: Onboarding a new harness in two PRs where the adapter lands first; renaming a target id in one place only; deleting an adapter without pruning the catalog; merge conflicts resolved by keeping the adapter but dropping the catalog line.

Related errors


AI-assisted analysis of affaan-m/ECC@d8409a4b08 (2026-08-26). Data as JSON: /api/errors/5f235d214d5cd6a6. Report an issue: GitHub.