Skip to content

FormatString false positive on a switch-expression argument to printf("%d", ...) #5831

@Chordrain

Description

@Chordrain

Error Prone version

Error Prone 2.49.0 (javac plugin) — javac 21.0.8, source/target 21.

Check name

FormatStringhttps://errorprone.info/bugpattern/FormatString

Description

FormatString validates that printf-style format strings match their arguments. When the argument is an int-typed switch expression passed directly to %d, the check fails to resolve the argument's type and falsely reports an illegal format conversion. The diagnostic even names an internal sentinel class (com.google.errorprone.bugpatterns.formatstring.FormatStringValidation$...) as the argument type, confirming the type resolution falls back to a placeholder for switch-expression arguments.

This is a false positive (the strongest finding in this batch): the same value passed via a var temporary is accepted, but inlining the switch expression triggers a spurious error.

Reproducer

// BEFORE — 0 findings (int routed through a var temporary)
public class C {
  static final int FRIDAY = 5;
  public static void main(String[] args) {
    int day = FRIDAY;
    var numLetters = switch (day) {
      case 1, 5, 7 -> 6;
      case 2 -> 7;
      default -> 9;
    };
    System.out.printf("NumLetters: %d%n", numLetters);
  }
}
// AFTER — equivalent inlining, 1 spurious finding
public class C {
  static final int FRIDAY = 5;
  public static void main(String[] args) {
    int day = FRIDAY;
    System.out.printf("NumLetters: %d%n", switch (day) {
      case 1, 5, 7 -> 6;
      case 2 -> 7;
      default -> 9;
    });
  }
}

Expected behavior

FormatString should report nothing on either form. The switch expression has static type int, which is compatible with %d, exactly like the var temporary in BEFORE.

Actual behavior

  • BEFORE: 0 findings.
  • AFTER: 1 finding — illegal format conversion: 'com.google.errorprone.bugpatterns.formatstring.FormatStringValidation$...' ...

The type of a switch-expression argument is not resolved; the check substitutes an internal sentinel type and emits a false illegal format conversion.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions