JetBrains/intellij-community · error · FormatDecode.IllegalFormatException

unexpected character ''{0}'' in ''{1}''

Error message

unexpected character ''{0}'' in ''{1}''

What it means

IllegalFormatException from FormatDecode when a flag character inside a format specifier is not recognized at all — flag(flag) returned -1. Recognized flags are '-','#','+',' ','0',',' and '('; anything else in the flags region (which the regex may capture loosely, e.g. letters) triggers this. It is the 'unexpected character' variant, distinct from disallowed-but-known flags.

Source

Thrown at java/java-analysis-impl/src/com/siyeh/ig/format/FormatDecode.java:253

      //theoretically, it could be a correct specifier, divided into several parts, for example: "%1$t" + "Y"
      //it is better to add ALL_VERIFIER
      if (noVerify || isPrefix && i == formatString.length()) {
        isAllVerifier = true;
      }
      final String specifier = matcher.group();
      final String posSpec = matcher.group("posSpec");
      final String flags = matcher.group("flags");
      final String width = matcher.group("width");
      final String precision = matcher.group("precision");
      final String dateSpec = matcher.group("dateSpec");
      final @NonNls String conversion = matcher.group("conversion");

      int flagBits = 0;
      for (int j = 0; j < flags.length(); j++) {
        final char flag = flags.charAt(j);
        final int bit = flag(flag);
        if (bit == -1) {
          throw new IllegalFormatException(InspectionGadgetsBundle.message("format.string.error.unexpected.flag", flag, specifier));
        }
        if ((flagBits | bit) == flagBits) {
          throw new IllegalFormatException(InspectionGadgetsBundle.message("format.string.error.duplicate.flag", flag, specifier));
        }
        flagBits |= bit;
      }

      // check this first because it should not affect "implicit"
      if ("n".equals(conversion)) {
        // no flags allowed
        checkFlags(flagBits, 0, specifier);
        if (!StringUtil.isEmpty(width)) {
          throw new IllegalFormatException(InspectionGadgetsBundle.message("format.string.error.width.not.allowed", width, specifier));
        }
        checkNoPrecision(precision, specifier);
        continue;
      }
      else if ("%".equals(conversion)) { // literal '%'

View on GitHub (pinned to be881553f2)

Solutions

  1. Correct the specifier to use only legal flags: '- # + 0 , ('
  2. Escape literal percent as '%%' instead of a malformed specifier
  3. Re-run the inspection after fixing to catch follow-on errors

Example fix

// before
String.format("%=5d", 42)
// after
String.format("%5d", 42)
Defensive patterns

Strategy: validation

Validate before calling

private static final Set<Character> KNOWN_FLAGS = Set.of('-', '#', '+', ' ', '0', ',', '(');
static boolean flagsRecognized(String flags) {
  return flags.chars().allMatch(c -> KNOWN_FLAGS.contains((char) c));
}

Try / catch

try { FormatDecode.decode(fmt, argc); } catch (IllegalFormatException e) { /* point at the specifier containing the unknown character */ }

Prevention

When it happens

Trigger: A specifier whose flags area contains an unrecognized character, e.g. '%=5d' or '%l5d'; typically from typos or regex-loose matching of malformed specifiers during decode().

Common situations: Typos in format strings; converting from other format dialects (MessageFormat, python) leaving stray characters; smart-quote corruption when pasting.

Related errors


AI-assisted analysis of JetBrains/intellij-community@be881553f2 (2026-08-14). Data as JSON: /api/errors/f1f939a0b66c7d43. Report an issue: GitHub.