Scott Murphy Heiberg created GROOVY-12732:
---------------------------------------------
Summary: groovy command logs "Caught: {0}" without filling the
placeholder and prints the stack trace twice
Key: GROOVY-12732
URL: https://issues.apache.org/jira/browse/GROOVY-12732
Project: Groovy
Issue Type: Bug
Components: command line processing
Affects Versions: 6.0.0
Reporter: Scott Murphy Heiberg
When a script throws, the {{groovy}} command logs its message with the
placeholder unfilled, then prints the exception's stack trace twice: first
unsanitized, through the logger, then sanitized, by {{printStackTrace()}}.
Throws.groovy:
{code:groovy}
throw new IllegalStateException('boom')
{code}
Groovy 6.0.0 on JDK 25:
{noformat}
$ groovy Throws.groovy
Nov 07, 2026 10:58:15 PM groovy.ui.GroovyMain run
SEVERE: Caught: {0}
java.lang.IllegalStateException: boom
at Throws.run(Throws.groovy:1)
at
groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:322)
at groovy.lang.GroovyShell.run(GroovyShell.java:468)
at groovy.lang.GroovyShell.run(GroovyShell.java:457)
at groovy.ui.GroovyMain.processOnce(GroovyMain.java:851)
at groovy.ui.GroovyMain.run(GroovyMain.java:450)
at groovy.ui.GroovyMain$GroovyCommand.process(GroovyMain.java:355)
at groovy.ui.GroovyMain.processArgs(GroovyMain.java:168)
at groovy.ui.GroovyMain.main(GroovyMain.java:127)
at
java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:565)
at
org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:150)
at org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:52)
java.lang.IllegalStateException: boom
at Throws.run(Throws.groovy:1)
{noformat}
The 6.0.1-SNAPSHOT and master behave the same. Before GROOVY-11886 the command
printed {{Caught: java.lang.IllegalStateException: boom}} and then the
sanitized trace once.
Cause: GROOVY-11886 replaced {{System.err.println("Caught: " + e)}} in
{{GroovyMain.run()}} with
{code:java}
LOGGER.log(ERROR, "Caught: {0}", e);
{code}
Because {{e}} is a {{Throwable}}, Java selects {{System.Logger.log(Level,
String, Throwable)}} rather than {{log(Level, String, Object...)}}. The message
is not formatted, and the throwable is logged with its full stack trace before
{{StackTraceUtils.deepSanitize}} runs, so that copy ignores the {{-d}} setting.
The other logging calls with a \{0\} placeholder pass arguments that are not
throwables and are not affected.
The line was noticed, as a side note, in the description of GROOVY-12683.
Proposed fix: log the text only, {{LOGGER.log(ERROR, "Caught: " + e)}}, and
keep the single sanitized {{printStackTrace()}}. A pull request with a test in
GroovyMainTest follows.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)