affaan-m/ECC · error · Error

Unsupported guided harness: ${id}

Error message

Unsupported guided harness: ${id}

What it means

Thrown by createMultiHarnessPlan when request.harnesses contains an id that is not 'claude', 'codex', or 'kimi'. The guided installer only supports those three harnesses; an unknown id means the request was malformed upstream. normalizeGuidedInstallRequest is supposed to validate the harness list earlier, so reaching this branch implies the harness array was injected/modified after normalization or normalization was bypassed.

Source

Thrown at scripts/lib/multi-harness-setup.js:394

}

async function createMultiHarnessPlan(request, injected = {}, options = {}) {
  const dependencies = { ...defaultDependencies(options), ...injected };
  let entries = [];
  for (const id of request.harnesses) {
    if (id === 'claude') {
      entries = [...entries, { id, channel: 'native-plugin', preview: await dependencies.previewClaude(request) }];
    } else if (id === 'codex') {
      entries = [...entries, { id, channel: 'native-plugin', preview: await dependencies.previewCodex(request) }];
    } else if (id === 'kimi') {
      const managedPlan = await dependencies.createManagedPlan(request);
      entries = [...entries, {
        id,
        channel: 'managed-project',
        preview: await dependencies.preflightManaged(managedPlan),
      }];
    } else {
      throw new Error(`Unsupported guided harness: ${id}`);
    }
  }
  return { harnesses: entries, request };
}

async function applyMultiHarnessPlan(plan, injected = {}, options = {}) {
  const dependencies = { ...defaultDependencies(options), ...injected };
  if (plan.request.dryRun) {
    return { status: 'preview', completed: [], retryHarnesses: [...plan.request.harnesses] };
  }

  let completed = [];
  for (let index = 0; index < plan.harnesses.length; index += 1) {
    const entry = plan.harnesses[index];
    try {
      let result;
      if (entry.id === 'claude') result = await dependencies.applyClaude(plan.request, entry);
      else if (entry.id === 'codex') result = await dependencies.applyCodex(plan.request, entry);

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Route user input through normalizeGuidedInstallRequest first; it rejects unsupported harnesses early with a clearer message.
  2. Restrict request.harnesses to the set ['claude','codex','kimi'].
  3. If you need to add a harness, extend this dispatcher and the normalizer together — do not pass an unknown id.
  4. Check for case/whitespace in the id and normalize to lowercase before dispatch.

Example fix

// before: caller bypasses normalization
const plan = await createMultiHarnessPlan({ harnesses: ['cursor'] }); // throws [295]

// after: validate via the normalizer, which only allows claude/codex/kimi
const req = normalizeGuidedInstallRequest({ harnesses: ['claude','kimi'] });
const plan = await createMultiHarnessPlan(req);
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED = new Set(['claude','codex','kimi']);
function assertSupportedHarnesses(harnesses) {
  const bad = harnesses.filter(id => !SUPPORTED.has(id));
  if (bad.length) throw new Error(`Unsupported harness id(s): ${bad.join(', ')}. Supported: claude, codex, kimi.`);
}
assertSupportedHarnesses(request.harnesses);
// or simply route through normalizeGuidedInstallRequest, which validates for you
const safeReq = normalizeGuidedInstallRequest({ harnesses: request.harnesses });

Type guard

function isSupportedHarness(id) {
  return id === 'claude' || id === 'codex' || id === 'kimi';
}

Try / catch

try {
  await createMultiHarnessPlan(req);
} catch (err) {
  if (/Unsupported guided harness/.test(err.message)) {
    req.harnesses = req.harnesses.filter(isSupportedHarness);
    if (!req.harnesses.length) throw new Error('No supported harnesses selected.');
    await createMultiHarnessPlan(req);
  } else throw err;
}

Prevention

When it happens

Trigger: Fires in the else branch of the harness id chain in createMultiHarnessPlan. Reached when an id in request.harnesses is not one of the three supported strings. Happens if a caller constructs the request manually without normalizeGuidedInstallRequest, passes uppercase/whitespace variants that bypassed normalization, or forwards an id from user input not in the allowed set.

Common situations: Caller builds {harnesses:['cursor']} or ['windsurf'] directly; case mismatch like 'Claude' if normalization was skipped; user-supplied harness name forwarded to createMultiHarnessPlan without validation; programmatic integration that extended harnesses without updating this dispatcher.

Related errors


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