affaan-m/ECC · error · Error

No legacy languages were provided

Error message

No legacy languages were provided

What it means

Thrown by resolveLegacyCompatibilitySelection() when dedupeStrings(options.legacyLanguages) — after lowercasing — yields an empty array. The legacy path requires at least one language because its whole purpose is to install language-specific rule modules. Calling it without languages is a no-op the library refuses to silently perform.

Source

Thrown at scripts/lib/install-manifests.js:483

    .map(exclusion => ({ ...exclusion }));
}

function resolveLegacyCompatibilitySelection(options = {}) {
  const manifests = loadInstallManifests(options);
  const target = options.target || null;

  if (target && !SUPPORTED_INSTALL_TARGETS.includes(target)) {
    throw new Error(
      `Unknown install target: ${target}. Expected one of ${SUPPORTED_INSTALL_TARGETS.join(', ')}`
    );
  }

  const legacyLanguages = dedupeStrings(options.legacyLanguages)
    .map(language => language.toLowerCase());
  const normalizedLegacyLanguages = dedupeStrings(legacyLanguages);

  if (normalizedLegacyLanguages.length === 0) {
    throw new Error('No legacy languages were provided');
  }

  const unknownLegacyLanguages = normalizedLegacyLanguages
    .filter(language => !Object.hasOwn(LEGACY_LANGUAGE_ALIAS_TO_CANONICAL, language));

  if (unknownLegacyLanguages.length === 1) {
    throw new Error(
      `Unknown legacy language: ${unknownLegacyLanguages[0]}. Expected one of ${listLegacyCompatibilityLanguages().join(', ')}`
    );
  }

  if (unknownLegacyLanguages.length > 1) {
    throw new Error(
      `Unknown legacy languages: ${unknownLegacyLanguages.join(', ')}. Expected one of ${listLegacyCompatibilityLanguages().join(', ')}`
    );
  }

  const canonicalLegacyLanguages = normalizedLegacyLanguages

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Pass at least one language, e.g. legacyLanguages: ['rust'] or ['typescript', 'python'].
  2. If you do not want legacy language modules, call resolveInstallPlan() instead.
  3. Guard the call: if (langs.length === 0) return resolveInstallPlan(opts).
  4. Use listLegacyCompatibilityLanguages() to surface valid values to the end user.

Example fix

// before
resolveLegacyCompatibilitySelection({ target: 'claude', legacyLanguages: langs });
// after
if (!Array.isArray(langs) || langs.length === 0) {
  return resolveInstallPlan({ target: 'claude' });
}
resolveLegacyCompatibilitySelection({ target: 'claude', legacyLanguages: langs });
Defensive patterns

Strategy: validation

Validate before calling

const langs = dedupe((options.legacyLanguages || []).map(l => String(l || '').toLowerCase()));
if (langs.length === 0) {
  // legacy mode is opt-in — fall back to plain plan
  return resolveInstallPlan({ target: options.target });
}
resolveLegacyCompatibilitySelection({ ...options, legacyLanguages: langs });

Prevention

When it happens

Trigger: Calling resolveLegacyCompatibilitySelection({}) with no legacyLanguages, or with legacyLanguages: [], or with values that dedupe down to nothing (e.g. [null, undefined]).

Common situations: A CLI defaulted legacyLanguages to an empty array when no --lang flag was passed; a wrapper script conditionally builds the list and the branch produced nothing; the caller confused resolveLegacyCompatibilitySelection with resolveInstallPlan.

Related errors


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