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)

Reply via email to