JetBrains/intellij-community · error · FormatDecode.IllegalFormatException
unnecessary argument position specifier ''{0}'' in ''{1}''
Error message
unnecessary argument position specifier ''{0}'' in ''{1}'' What it means
IllegalFormatException from FormatDecode when an explicit argument-position specifier like '2$' is combined with the '<' (previous argument) flag in the same specifier — e.g. '%2$<d'. The two addressings are mutually exclusive: posSpec selects an argument index, '<' reuses the previous one; having both is meaningless, so decode() rejects it.
Source
Thrown at java/java-analysis-impl/src/com/siyeh/ig/format/FormatDecode.java:279
// 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 '%'
checkFlags(flagBits, LEFT_JUSTIFY, specifier);
checkNoPrecision(precision, specifier);
continue;
}
if (posSpec != null) {
if (isAllBitsSet(flagBits, PREVIOUS)) {
throw new IllegalFormatException(
InspectionGadgetsBundle.message("format.string.error.unnecessary.position.specifier", posSpec, specifier));
}
final String num = posSpec.substring(0, posSpec.length() - 1);
pos = Integer.parseInt(num) - 1;
if (pos < 0) {
throw new IllegalFormatException(
InspectionGadgetsBundle.message("format.string.error.illegal.position.specifier", posSpec, specifier));
}
previousAllowed = true;
}
else if (isAllBitsSet(flagBits, PREVIOUS)) {
// reuse last pos
if (!previousAllowed) {
throw new IllegalFormatException(InspectionGadgetsBundle.message("format.string.error.previous.element.not.found", specifier));
}
}
else {
previousAllowed = true;View on GitHub (pinned to be881553f2)
Solutions
- Keep exactly one addressing style per specifier: either 'N$' or '<', not both
- Prefer one consistent style (all indexed or all relative) across the whole format string
Example fix
// before
String.format("%1$<s %s", "a", "b")
// after
String.format("%1$s %2$s", "a", "b") Defensive patterns
Strategy: validation
Validate before calling
static boolean addressingConsistent(String posSpec, boolean hasPreviousFlag) {
return !(posSpec != null && hasPreviousFlag); // 'N$' and '<' are mutually exclusive
} Try / catch
try { FormatDecode.decode(fmt, argc); } catch (IllegalFormatException e) { /* remove '<' or the index from the specifier */ } Prevention
- Pick one addressing style per format string and stick to it
When it happens
Trigger: A specifier containing both an index like 'N$' and a '<' flag, e.g. '%1$<s'; posSpec != null and PREVIOUS bit set.
Common situations: Hand-merging format specifiers when reordering arguments; copy-paste mixing relative and indexed styles in one string.
Related errors
- {2, choice, 1#flag|1<flags} ''{0}'' not allowed in ''{1}''
- unexpected character ''{0}'' in ''{1}''
- duplicate flag ''{0}'' in ''{1}''
- width (''{0}'') not allowed in ''{1}''
- previous flag ''<'' used but no previous format specifier fo
AI-assisted analysis of JetBrains/intellij-community@be881553f2 (2026-08-14).
Data as JSON: /api/errors/88754ed1f310dfb3.
Report an issue: GitHub.