Jenkins Error: 'groovy.lang.MissingPropertyException: No such property: <name> for class: WorkflowScript' — Cause, Fix, and Troubleshooting Guide
Fix Jenkins 'groovy.lang.MissingPropertyException: No such property for class: WorkflowScript': resolve undefined vars, scope, params vs env, and imports.
- #jenkins
- #ci-cd
- #troubleshooting
- #errors
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
Overview
Your Jenkinsfile referenced a variable that Groovy cannot resolve at that point in the script. WorkflowScript is the class Jenkins compiles your Pipeline into, so “No such property … for class: WorkflowScript” means: at the top level of your pipeline, there is no binding, no def, no parameter, and no environment entry with that name in scope.
groovy.lang.MissingPropertyException: No such property: IMAGE_TAG for class: WorkflowScript
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:...)
at WorkflowScript.run(WorkflowScript:23)
The class name after “for class:” tells you where the lookup happened — WorkflowScript is your Jenkinsfile, a shared-library class name points into src/, and a step name points inside that step’s closure. Almost always this is a typo, a scoping mistake (a def that is not visible where you use it), confusion between params/env/global variables, or a variable used before it was assigned.
Symptoms
- The pipeline fails at compile/run time with
MissingPropertyException: No such property: <name> for class: WorkflowScript. - It fails on a specific line that references a bare identifier (e.g.
echo IMAGE_TAGrather thanecho env.IMAGE_TAG). - A variable set inside one block is “undefined” when read in another block or stage.
- The value exists as a build parameter or environment variable, but you referenced it by the wrong accessor.
- The error appears only after a rename, a copy-paste between Jenkinsfiles, or moving code into a shared library.
Common Root Causes
- Typo or wrong case —
imageTagvsIMAGE_TAGvsimage_tag; Groovy property lookup is exact and case-sensitive. - Out-of-scope
def— a variable declared withdefinside a closure/stage is local to that block and is not visible elsewhere; reading it later throws. - Using a variable before assignment — the reference executes on a path where the variable was never set (e.g. only assigned inside an
if). - params vs env vs global confusion — a build parameter is
params.NAME, an environment variable isenv.NAME; referencing a bareNAMEat top level only works if a global/binding of that exact name exists. - Missing shared-library import — a global variable or class provided by a shared library is referenced without
@Libraryimporting it, so the name is unbound. - Relying on
deffor a cross-stage variable in declarative — declarative pipelines evaluateenvironment {}and stages differently; a top-leveldefmay not be visible where you expect.
How to diagnose
Read the property name and the class. for class: WorkflowScript means the Jenkinsfile top level; a different class name points into a shared library. Then check how the value is actually supposed to be supplied.
Confirm what parameters and environment the build actually has. Add a temporary debug step:
// Temporary: what is actually in scope?
echo "params: ${params}" // all build parameters
echo "env keys: ${env.getEnvironment().keySet()}" // env variable names
For declarative pipelines, dump the environment from a shell step to see exactly what is exported:
steps {
sh 'printenv | sort' // shows env.* exported to the shell
}
Use Replay (in the build’s left menu) to edit the Jenkinsfile inline and re-run quickly while you locate the bad reference. Grep the repo for the name to catch a declaration/scope mismatch:
# Where is the name defined vs used?
grep -RnE '\bIMAGE_TAG\b' Jenkinsfile vars/ src/
Fixes
1. Reference parameters and environment with the right accessor
A build parameter is on params; an environment variable is on env. Do not reference them as bare identifiers.
pipeline {
agent any
parameters {
string(name: 'IMAGE_TAG', defaultValue: 'latest', description: 'Image tag to deploy')
}
stages {
stage('Deploy') {
steps {
// WRONG: echo IMAGE_TAG -> No such property: IMAGE_TAG
echo "Deploying ${params.IMAGE_TAG}" // build parameter
echo "Build URL: ${env.BUILD_URL}" // environment variable
}
}
}
}
2. Declare cross-stage variables at the right scope
In a scripted pipeline, declare the variable at node/script scope (not inside the block that first sets it) so later stages can read it. In declarative, set it into env or use a script-level variable:
// Scripted: declare once at the top so every stage sees it
node {
def imageTag // visible to the whole node block
stage('Build') {
imageTag = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
}
stage('Deploy') {
sh "deploy --tag ${imageTag}" // in scope here
}
}
For declarative pipelines, promote the value into env so it survives across stages:
pipeline {
agent any
stages {
stage('Build') {
steps {
script { env.IMAGE_TAG = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim() }
}
}
stage('Deploy') {
steps { sh 'deploy --tag "$IMAGE_TAG"' } // env.IMAGE_TAG is exported
}
}
}
3. Guard against use-before-assignment
If a variable is only set on some paths, give it a default so a read never hits an unbound name:
def artifact = '' // default so it is always defined
if (fileExists('target/app.jar')) {
artifact = 'target/app.jar'
}
echo "artifact: ${artifact ?: 'none built'}"
4. Import the shared library that defines the name
If the missing property is a shared-library global variable (a file under vars/) or class, import the library so the binding exists:
@Library('my-shared-lib@main') _ // the trailing _ imports global vars
pipeline {
agent any
stages {
stage('Notify') {
steps { notifySlack('build ok') } // vars/notifySlack.groovy
}
}
}
Confirm the library is registered under Manage Jenkins → System → Global Pipeline Libraries with the exact name you referenced.
5. Fix the typo
The dull-but-common answer: the name is misspelled or mis-cased. Groovy will not fuzzy-match. Compare the reference to the declaration character for character — IMAGE_TAG and Image_Tag are different properties.
What to watch out for
- The name after
No such property:is exactly what Groovy looked up — search for that literal string; do not assume it is the variable you think you used. - Bare identifiers only resolve to Pipeline global variables or script bindings. For parameters use
params.X, for environment useenv.X(or$Xinside ashstring). - A
definside a stage/closure is local to that block. If two stages need it, declare it atnode/script scope or store it inenv. env.Xvalues are always strings — assigning a number or boolean gets coerced; compare accordingly.- After adding a shared-library global, remember the
@Library(...) _line (with the underscore) or the global stays unbound. - The free incident assistant can point at the offending line from a pasted stack trace.
Related
- Jenkins Error: unable to resolve class — the compile-time sibling: a class (not a property) that Groovy cannot find, usually a missing import.
- Jenkins Error: No such DSL method — the same “not found” failure for a pipeline step/method rather than a property.
- Jenkins Error: java.io.NotSerializableException — another common Jenkinsfile Groovy/CPS scripting failure.
More Jenkins prompts & error guides
Every Jenkins AI prompt and troubleshooting guide, in one place.
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.