Captured from a real `junit-platform-console-standalone --details=tree` run against CsvSourceTest#testPublishingPermissions, compiled and executed for real. ╷ ├─ JUnit Platform Suite ✔ ├─ JUnit Jupiter ✔ │ └─ CsvSourceTest ✔ │ └─ testPublishingPermissions(int, String, boolean) ✔ │ ├─ user USER_ID = "1001" with role ROLE = "EDITOR" ✔ │ ├─ user USER_ID = "1002" with role ROLE = "ADMIN" ✔ │ └─ user USER_ID = "1003" with role ROLE = "USER" ✔ └─ JUnit Vintage ✔ Test run finished after 228 ms [ 3 tests successful ] [ 0 tests failed ] This is the genuinely new, easy-to-miss finding in this rewrite. The custom template is name = "user {0} with role {1}" -- plain positional placeholders, the same {0}/{1} syntax used everywhere else in this module. But because @CsvSource(useHeadersInDisplayName = true) is also set, each individual {0} and {1} does not resolve to the bare value ("1001", "EDITOR") the way it would without that flag -- it resolves to "HEADER = value" ("USER_ID = \"1001\"", "ROLE = \"EDITOR\""). useHeadersInDisplayName changes what every positional placeholder expands to, not just the auto-generated default name used when no custom name is given at all. Compare this against docs/output/05-csv-source-headers-default-display-name.txt (no custom name, same data, same flag) and docs/output/06-header-name-placeholder-throws.txt (an attempt to put the header name directly inside the template, which is a different thing entirely and throws).