Issue
Pipeline builds fail with the exception that looks like following:
groovy.lang.MissingPropertyException: No such property: env for class: groovy.lang.Binding at groovy.lang.Binding.getVariable(Binding.java:63) at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:270) at org.kohsuke.groovy.sandbox.impl.Checker$6.call(Checker.java:291) at org.kohsuke.groovy.sandbox.GroovyInterceptor.onGetProperty(GroovyInterceptor.java:68) at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:354) at org.kohsuke.groovy.sandbox.impl.Checker$6.call(Checker.java:291) at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:295) at org.kohsuke.groovy.sandbox.impl.Checker$checkedGetProperty$1.callStatic(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:56) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:194) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:230) at Script5.<init>(Script5.groovy:10) ... Finished: FAILURE
Environment
-
CloudBees CI (CloudBees Core) on modern cloud platforms - Managed controller
-
CloudBees CI (CloudBees Core) on traditional platforms - Client controller
-
CloudBees Jenkins Enterprise - Managed controller
Resolution
Inspect recent changes to the Pipeline Definition looking for the following pattern:
// a.groovy import groovy.transform.Field @Field def LOADED_BUILD_NUMBER = "${env.BUILD_NUMBER}" return this
// Jenkinsfile node() { checkout scm def a = load('a.groovy') echo("${env.BUILD_NUMBER}") echo("${a.LOADED_BUILD_NUMBER}") }
If it is the case you are affected by the known issue [JENKINS-63384] load step fails to bind "complex" @Field defined variables. At the time of the writing (2 Oct 2020) there is no fix for it.
Workaround
Rewriting the load
-ed Groovy script to avoid using of @Field
initialized with values global variables. For example above script can be re-written:
// a.groovy class BuildValueObject { def LOADED_BUILD_NUMBER BuildValueObject(script) { this.LOADED_BUILD_NUMBER = "${script.env.BUILD_NUMBER}" } } return new BuildValueObject(this)