Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-65054

DSL steps resolver error "No such DSL method" is confusing when named method, step or global exists but signature does not match



    • Bug
    • Status: Open (View Workflow)
    • Minor
    • Resolution: Unresolved
    • workflow-cps-plugin
    • None
    • workflow-cps-plugin 2.90
      jenkins 2.282


      If a DSL method exists in the current binding but its method signature does not match, the workflow-cps-plugin will raise the error

      java.lang.NoSuchMethodError: No such DSL method 'wrong_signature' found among steps [...long-list-of-steps-and-vars-and-globals....]
      	at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:202)
      	at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:122)
      	at sun.reflect.GeneratedMethodAccessor3619.invoke(Unknown Source)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
      	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
      	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1213)
      	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
      	at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:42)
      	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
      	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
      	at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:163)
      	at org.kohsuke.groovy.sandbox.GroovyInterceptor.onMethodCall(GroovyInterceptor.java:23)
      	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:157)
      	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:142)
      	at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:161)
      	at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:165)
      	at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:17)
      	at WorkflowScript

      See DSL.java

      This will be emitted even if there's a local function in scope and its method signature does not match - which is extraordinarily confusing since the local function will not be listed in candidate steps list.

      For example, this `Jenkinsfile` would do it:

      def mismatched_signature(Map args) {

      In Groovy, without the workflow steps binding, you'd instead get:

      $ groovy /tmp/test.groovy 
      Caught: groovy.lang.MissingMethodException: No signature of method: test.mismatched_signature() is applicable for argument types: (String) values: [foo]
      Possible solutions: mismatched_signature(java.util.Map)
      groovy.lang.MissingMethodException: No signature of method: test.mismatched_signature() is applicable for argument types: (String) values: [foo]
      Possible solutions: mismatched_signature(java.util.Map)
      	at test.run(test.groovy:5)
      	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

      which tells the user that a matching name was found, but no method on that name could be resolved.

      This is a much more informative result.

      This was a big usability challenge for me when learning the cps pipeline system, so I thought I'd raise it here.

      It would be very helpful if the resolver could generate the original original Groovy resolution exception as a cause, or arrange for the original Groovy resolution to wrap the DSL steps exception.

      Arguably there are two problems here:

      • If a name match for a called method is found in the script's scope, but the signature does not match, the CPS steps resolver takes over and tries to find the method in the set of available steps and globals. If it fails to do so, it raises the same java.lang.NoSuchMethodError as would be raised when no name matched in the script's scope at all. The Groovy method resolution exception groovy.lang.MissingMethodException that might tell the script author what's wrong is never generated or thrown. Because the steps list in the exception thrown by DSL.java doesn't list script-locals, the existing name with mismatched signature is not listed in the steps candidates in the exception, further misleading the user into thinking the named method not exist at all in the current scope. In reality is does, just with an incompatible signature, but this is completely obscured.
      • If a name match for a called global var or step is found by DSL.java, but the signature does not match, then java.lang.NoSuchMethodError} is thrown instead of an informative {{groovy.lang.MissingMethodException with overload resolution hints.



          There are no comments yet on this issue.


            Unassigned Unassigned
            ringerc Craig Ringer
            0 Vote for this issue
            1 Start watching this issue