affaan-m/ECC · error

Harness capability root is out of sync for target

Error message

Harness capability root is out of sync for target ${declaredScope.targetId}

What it means

validateCatalog checks each harness-declared scope against the corresponding install-target adapter: the adapter must exist and expectedRootForAdapter(adapter) must equal the scope's declared root. Any mismatch throws this message naming the offending targetId. It guarantees declared scope roots stay in sync with adapter-derived filesystem roots.

Solutions

  1. Fix the targetId typo or point the scope at an existing adapter id.
  2. Update the scope's declared root in HARNESS_CAPABILITIES to match expectedRootForAdapter(adapter).
  3. Run the catalog tests after any change to adapter root logic to re-derive expected roots.
  4. If the layout changed intentionally, update both the adapter and every scope declaration referencing it.

Example fix

// before
{ targetId: 'skills', root: 'skills' } // adapter now derives '.agents/skills'

// after
{ targetId: 'skills', root: '.agents/skills' }
Defensive patterns

Strategy: validation

Validate before calling

for (const harness of HARNESS_CAPABILITIES) {
  for (const scope of harness.scopes) {
    const adapter = adapterByTarget.get(scope.targetId);
    if (!adapter || expectedRootForAdapter(adapter) !== scope.root) {
      throw new Error(`Scope root mismatch for ${scope.targetId}: declared ${scope.root}`);
    }
  }
}

Try / catch

try {
  validateCatalog();
} catch (e) {
  const m = /root is out of sync for target (\S+)/.exec(e.message);
  if (m) console.error(`Fix scope root or targetId for: ${m[1]}`);
  throw e;
}

Prevention

When it happens

Trigger: Changing an adapter's root path logic (expectedRootForAdapter) without updating the hardcoded root in HARNESS_CAPABILITIES scopes; a typo in a scope's targetId so adapterByTarget.get returns undefined; adding a scope entry with a stale root after a directory-layout change.

Common situations: Refactoring install directories (e.g. moving skills from skills/ to .agents/skills/) and updating the adapter but not the catalog; renaming a target id in adapters only; a new harness scope entry copied from another harness with the wrong root.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

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

  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();
}

function listGuidedHarnesses() {
  return GUIDED_HARNESS_IDS.map(id => LOOKUP.get(id));
}

function getHarnessCapability(value) {

View on GitHub (pinned to 8321021c54)