affaan-m/ECC · error

--locale can only be used with --target claude or --target…

Error message

--locale can only be used with --target claude or --target claude-project

What it means

normalizeInstallRequest restricts locale installation to the Claude targets. If a valid locale is supplied but the resolved target is neither 'claude' nor 'claude-project', it throws this error. Translated component sets only exist for Claude targets, so combining a locale with another --target (e.g. codex, cursor) is rejected.

Solutions

  1. Change the target: use `--target claude` or `--target claude-project` with the locale.
  2. Drop the `--locale` flag (and any `locale` key in your install config) when targeting a non-Claude harness.
  3. Run two installs: a translated Claude install, then a separate non-Claude install without a locale.
  4. Check the resolved target — config files may set a target you didn't pass explicitly.

Example fix

// before
install --target codex --locale ja-JP

// after
install --target claude --locale ja-JP
Defensive patterns

Strategy: validation

Validate before calling

if (options.locale && !['claude', 'claude-project'].includes(options.target)) {
  throw new Error('--locale requires --target claude or --target claude-project');
}

Type guard

function localeTargetCompatible(opts) {
  return !opts.locale || opts.target === 'claude' || opts.target === 'claude-project';
}

Try / catch

try {
  const req = normalizeInstallRequest(options);
} catch (e) {
  if (e.message.includes('only be used with --target claude')) {
    console.error('Locale installs are Claude-only; drop --locale or switch the target.');
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Running the installer with both `--locale <code>` and `--target` set to anything other than `claude` or `claude-project` — e.g. `--target codex --locale ja-JP`, or a default/other target inherited from config while a locale is set in config.

Common situations: Installing the Codex or Cursor skill subset while a locale lingers in a config file; assuming translations are available cross-harness; scripting one install command and swapping --target without removing --locale.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at scripts/lib/install/request.js:111

function normalizeInstallRequest(options = {}) {
  const config = options.config && typeof options.config === 'object'
    ? options.config
    : null;
  const profileId = options.profileId || config?.profileId || null;
  const target = options.target || config?.target || 'claude';
  const moduleIds = validateInstallModuleIds(
    dedupeStrings([...(config?.moduleIds || []), ...(options.moduleIds || [])])
  );
  const locale = options.locale || config?.locale || null;
  const localeComponentId = locale ? LOCALE_ALIAS_TO_COMPONENT_ID[locale] : null;
  if (locale && !localeComponentId) {
    throw new Error(
      `Unsupported locale: "${locale}". Supported locales: ${listSupportedLocales().join(', ')}`
    );
  }
  if (locale && target !== 'claude' && target !== 'claude-project') {
    throw new Error('--locale can only be used with --target claude or --target claude-project');
  }
  const requestedIncludeComponentIds = dedupeStrings([
    ...(config?.includeComponentIds || []),
    ...(options.includeComponentIds || []),
  ]);
  const includeComponentIds = dedupeStrings([
    ...requestedIncludeComponentIds,
    ...(localeComponentId ? [localeComponentId] : []),
  ]);
  const excludeComponentIds = dedupeStrings([
    ...(config?.excludeComponentIds || []),
    ...(options.excludeComponentIds || []),
  ]);
  const legacyLanguages = dedupeStrings(dedupeStrings([
    ...(Array.isArray(options.legacyLanguages) ? options.legacyLanguages : []),
    ...(Array.isArray(options.languages) ? options.languages : []),
  ]).map(language => language.toLowerCase()));
  const hookConsent = resolveHookConsentFlags(options);

View on GitHub (pinned to 8321021c54)