Jenkins cps groovy does not catch NoSuchMethodError exceptions

Viewed 418

Is there anyway to catch NoSuchMethodError errors when the groovy code calls a method which doesn't exist?

The following code causes a NoSuchMethodError error which is not caught but the finally block does execute. This causes problems for some of my error handling and reporting.

Code with bogus dsl

try {
    println "in try"
    dslDoesNotExist()
} catch (Exception ex) {
    println "Caught error ${ex}"
    throw ex
} finally {
    println "finally block"
}

Result

in try
[Pipeline] echo
finally block    // see the finally but not the catch
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
java.lang.NoSuchMethodError: No such DSL method 'dslDoesNotExist'

If I modify the code about to reference a property/variable that does not exist the catch block is processed

Code with missing property

try {
    println "in try"
    propertyOrVariableDoesNotExist
} catch (Exception ex) {
    println "Caught error ${ex}"
    throw ex
} finally {
    println "finally block"
}

Result

in try
[Pipeline] echo
Caught error groovy.lang.MissingPropertyException: No such property: propertyOrVariableDoesNotExist for class: WorkflowScript
[Pipeline] echo
finally block
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
hudson.remoting.ProxyException: groovy.lang.MissingPropertyException: No such property: propertyOrVariableDoesNotExist for class: 

What is going on here

Java vs Groovy Exceptions?

Can CPS groovy catch(Exception ex) catch java.lang. exceptions? No

Code

    try {
        throw new java.lang.NoSuchMethodError("dsl problem")
    } catch (Exception ex) {
        println "Caught"
    }

Result

    // No evidence of the catch
    
    [Pipeline] { (hide)
    [Pipeline] }
    [Pipeline] // node
    [Pipeline] End of Pipeline
    java.lang.NoSuchMethodError: dsl problem
1 Answers

Thanks to @jeff-scott-brown as he was right. It took some digging and experimentation to figure this out. I was mistaken.

The ancestry of NoSuchMethodError looks like

 java.lang.Object
    java.lang.Throwable
        java.lang.Error
            java.lang.LinkageError
                java.lang.IncompatibleClassChangeError
                    java.lang.NoSuchMethodError 

The ancestry of Groovy Exception is

java.lang.Throwable
    java.lang.Exception
        org.codehaus.groovy.GroovyException 

So, if I refactor the code to this it works as expected. When I initially tested this, I hit a security sandbox error which obfuscated the results and I missed it (it was glaring so I don't know how I missed it, but I did)

Code

try {
    dslNotExist()
} catch (java.lang.Throwable ex) {
    println "Caught"
}

Result

[Pipeline] {
[Pipeline] echo
Caught
[Pipeline] }
[Pipeline] // node
Related