SonarSource/sonarqube · error · IllegalArgumentException

Locale cannot be parsed as a BCP47 language tag

Error message

Locale cannot be parsed as a BCP47 language tag

What it means

IndexAction (api/system/index) validates the mandatory locale parameter by parsing it as a BCP47 language tag: Locale.forLanguageTag plus getISO3Language must resolve to a known ISO3 language. If the tag is empty after parsing or unknown (MissingResourceException), IllegalArgumentException is thrown.

Solutions

  1. Use a valid BCP 47 language tag such as en, fr, de-DE
  2. Validate the tag client-side with Locale.forLanguageTag(tag).getISO3Language() before calling
  3. Check supported locales against the installed language packs; remove exotic/custom locale codes

Example fix

// before
const locale = 'english'; // invalid
await fetch(`/api/system/index?locale=${locale}`);

// after
const locale = 'en';
await fetch(`/api/system/index?locale=${encodeURIComponent(locale)}`);
Defensive patterns

Strategy: validation

Validate before calling

function isBcp47Tag(tag) { try { return Intl.getCanonicalLocales(tag).length > 0; } catch { return false; } }
if (!isBcp47Tag(locale)) throw new Error('invalid language tag');

Type guard

function isValidLocaleTag(tag) { return typeof tag === 'string' && /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]+)*$/.test(tag); }

Try / catch

try { await get(`/api/system/index?locale=${locale}`); } catch (e) { if (e.message.includes('BCP47')) { return get('/api/system/index?locale=en'); } throw e; }

Prevention

When it happens

Trigger: GET api/system/index with locale values like 'xx', 'qq-US', empty-ish tags, or strings that Locale.forLanguageTag silently maps to an undetermined locale; malformed tags with invalid characters.

Common situations: Passing custom/internal locale codes not in BCP 47; passing language names ('english') instead of tags ('en'); passing locales unsupported by the JVM's CLDR data.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/453be76fed13e90d. Report an issue: GitHub.

Appendix: source

Thrown at server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/IndexAction.java:79

      .setDefaultValue(ENGLISH.toLanguageTag());
    indexAction.createParam(TS_PARAM)
      .setDescription("Date of the last cache update.")
      .setExampleValue("2014-06-04T09:31:42+0000");
  }

  @Override
  public void handle(Request request, Response response) throws Exception {
    Date timestamp = request.paramAsDateTime(TS_PARAM);
    if (timestamp != null && timestamp.after(server.getStartedAt())) {
      response.stream().setStatus(HTTP_NOT_MODIFIED).output().close();
      return;
    }
    String localeParam = request.mandatoryParam(LOCALE_PARAM);
    Locale locale = Locale.forLanguageTag(localeParam);
    try {
      checkArgument(!locale.getISO3Language().isEmpty(), INVALID_LANGUAGE_TAG_MESSAGE);
    } catch (MissingResourceException e) {
      throw new IllegalArgumentException(INVALID_LANGUAGE_TAG_MESSAGE, e);
    }

    try (JsonWriter json = response.newJsonWriter()) {
      json.beginObject();
      json.prop("effectiveLocale", i18n.getEffectiveLocale(locale).toLanguageTag());
      json.name("messages");
      json.beginObject();
      i18n.getPropertyKeys().forEach(messageKey -> json.prop(messageKey, i18n.message(locale, messageKey, messageKey)));
      json.endObject();
      json.endObject();
    }
  }
}

View on GitHub (pinned to 184c821202)