affaan-m/ECC · critical · Error

Unsupported install target scope: ${scope}

Error message

Unsupported install target scope: ${scope}

What it means

Thrown by resolveBaseRoot(scope, input) in scripts/lib/install-targets/helpers.js. The function translates an adapter's configured kind into a base directory on disk; only 'home' (returns input.homeDir || os.homedir()) and 'project' (returns input.projectRoot || input.repoRoot, throwing if both are absent) are supported. Any other scope is an internal invariant violation: createInstallTargetAdapter only constructs adapters whose kind is one of these two, so the throw indicates a custom adapter registered with a novel kind or a caller invoking resolveBaseRoot directly with an unsupported value.

Source

Thrown at scripts/lib/install-targets/helpers.js:53

  }

  return false;
}

function resolveBaseRoot(scope, input = {}) {
  if (scope === 'home') {
    return input.homeDir || os.homedir();
  }

  if (scope === 'project') {
    const projectRoot = input.projectRoot || input.repoRoot;
    if (!projectRoot) {
      throw new Error('projectRoot or repoRoot is required for project install targets');
    }
    return projectRoot;
  }

  throw new Error(`Unsupported install target scope: ${scope}`);
}

function buildValidationIssue(severity, code, message, extra = {}) {
  return {
    severity,
    code,
    message,
    ...extra,
  };
}

function listRelativeFiles(dirPath, prefix = '') {
  if (!fs.existsSync(dirPath)) {
    return [];
  }

  const entries = fs.readdirSync(dirPath, { withFileTypes: true }).sort((left, right) => (
    left.name.localeCompare(right.name)

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Confirm the adapter's kind is exactly the string 'home' or 'project' — those are the only two scopes resolveBaseRoot branches on.
  2. If a genuinely new scope is required, add a branch in scripts/lib/install-targets/helpers.js that returns a concrete absolute path, and document it.
  3. Stop calling resolveBaseRoot directly; use adapter.resolveRoot(input), which forwards the adapter's configured kind.
  4. Audit the call site that produced the scope value — it almost certainly came from a hand-built adapter config object rather than createInstallTargetAdapter.

Example fix

// before
const adapter = createInstallTargetAdapter({
  id: 'foo', target: 'foo', kind: 'workspace',
  rootSegments: ['.foo'], installStatePathSegments: ['state.json'],
});
adapter.resolveRoot({}); // throws: Unsupported install target scope: workspace

// after
const adapter = createInstallTargetAdapter({
  id: 'foo', target: 'foo', kind: 'project',
  rootSegments: ['.foo'], installStatePathSegments: ['state.json'],
});
adapter.resolveRoot({ projectRoot: '/abs/path' });
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED_SCOPES = new Set(['home', 'project']);
function isValidAdapterKind(kind) {
  return SUPPORTED_SCOPES.has(kind);
}
// before registering or invoking:
if (!isValidAdapterKind(adapterConfig.kind)) {
  throw new TypeError(`Adapter kind '${adapterConfig.kind}' is unsupported; use 'home' or 'project'.`);
}

Type guard

function isAdapterKind(value) {
  return value === 'home' || value === 'project';
}

Prevention

When it happens

Trigger: Registering a custom adapter via createInstallTargetAdapter({ kind: 'workspace', ... }) and calling adapter.resolveRoot({}); calling resolveBaseRoot('user', {}) directly from outside helpers.js; a fork that adds a third scope without extending resolveBaseRoot.

Common situations: Forking ECC to add a new install surface and reusing 'kind' for a value that is neither 'home' nor 'project'; passing a typo'd kind string when constructing an adapter; version drift where a newer adapter definition emits a kind this older helpers.js does not recognize.

Related errors


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