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
- Change the target: use `--target claude` or `--target claude-project` with the locale.
- Drop the `--locale` flag (and any `locale` key in your install config) when targeting a non-Claude harness.
- Run two installs: a translated Claude install, then a separate non-Claude install without a locale.
- 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
- Only pass --locale together with an explicit Claude target.
- Scrub `locale` from install config files when targeting non-Claude harnesses.
- Assert flag/target compatibility in wrapper scripts before invoking the installer.
- Remember translations are Claude-specific — plan separate non-locale installs for Codex/Cursor.
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
- Legacy language arguments cannot be combined with…
- --no-hooks cannot be combined with an explicit…
- The all/* harness selection cannot be combined with other…
- Unsupported locale: " ". Supported locales
- all overlays must be readable local files
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)