# Jenkins Templating Engine: Library Binding Issue
## Problem Summary
JTE successfully loads libraries but templates cannot access them. Getting `MissingPropertyException: No such property: docker for class: WorkflowScript` despite logs showing `[JTE] Loading Library docker` succeeded.
## Environment
- **Jenkins Version**: 2.504.3 (also tested on CloudBees CI Managed Controller 2.492.1.3-rolling)
- **JTE Plugin Version**: 2.5.5 (Templating Engine)
- **Setup Type**: Multibranch Pipeline with Jenkins Templating Engine
- **Git Platform**: Azure DevOps (issue confirmed on GitHub as well)
- **Issue Confirmed On**: Two separate Jenkins instances with same results
## Repository Structure
### Template/Library Repository (jte-library-repo)
```
jte-library-repo/
├── templates/
│ ├── Jenkinsfile # Default template
│ ├── static-docker-ecr/
│ │ └── Jenkinsfile
│ └── node-docker-ecr/
│ └── Jenkinsfile
└── libraries/
├── docker/
│ └── steps/
│ └── buildImage.groovy
└── ecr/
└── steps/
└── push.groovy
```
### Application Repository (simple-test-app)
```
simple-test-app/
├── pipeline_config.groovy
├── Dockerfile
└── index.html
```
## Steps to Reproduce
### 1. Create Template/Library Repository
Create a Git repository named `jte-library-repo` with this structure:
```
jte-library-repo/
├── templates/
│ └── Jenkinsfile
└── libraries/
└── docker/
└── steps/
└── buildImage.groovy
```
**File: templates/Jenkinsfile**
```groovy
node {
stage("Checkout") {
checkout scm
}
stage("Docker Build") {
docker.buildImage()
}
}
```
**File: libraries/docker/steps/buildImage.groovy**
```groovy
void call() {
echo "\[Docker\] Building image: ${config.image}:${config.tag}"
}
```
### 2. Create Application Repository
Create a Git repository named `simple-test-app` with:
```
simple-test-app/
├── pipeline_config.groovy
└── Dockerfile
```
**File: pipeline_config.groovy**
```groovy
libraries {
docker {
image = "test-app"
tag = "1.0"
}
}
```
**File: Dockerfile**
```dockerfile
FROM alpine:latest
CMD [“echo”, “Hello”]
```
### 3. Configure Jenkins Global JTE Settings
Go to: **Manage Jenkins → Configure System → Jenkins Templating Engine**
Add Pipeline Configuration:
- Source: From SCM → Git
- Repository: [URL to jte-library-repo]
- Configuration Base Directory: `templates`
Add Library Source:
- Name: `jte-library-repo`
- Source: From SCM → Git
- Repository: [URL to jte-library-repo]
- Library Path: `libraries`
### 4. Create Multibranch Pipeline Job
1. New Item → Multibranch Pipeline
2. Branch Sources → Add Git source → [URL to simple-test-app]
3. Build Configuration:
- Mode: **Jenkins Templating Engine**
- Pipeline Configuration Path: `pipeline_config.groovy`
4. Save
### 5. Run Build
Click “Build Now” on the controller branch.
### Expected Result
```
[JTE] Loading Library docker
[Pipeline] stage (Docker Build)
[Docker] Building image: test-app:1.0
```
### Actual Result
```
[JTE] Loading Library docker ✓
[Pipeline] stage (Docker Build)
ERROR: No such property: docker for class: WorkflowScript
```
## Configuration
### Global Jenkins Configuration
**Manage Jenkins → Configure System → Jenkins Templating Engine**
```
Pipeline Configuration:
Source Location: From SCM
SCM: Git
Repository: https://your-company.visualstudio.com/DefaultCollection/YOUR_ORG/_git/jte-library-repo
Credentials: git-credentials
Branches to build: \*/master
Configuration Base Directory: templates
Library Sources:
Name: jte-library-repo
Source Location: From SCM
SCM: Git
Repository: https://your-company.visualstudio.com/DefaultCollection/YOUR_ORG/_git/jte-library-repo
Credentials: git-credentials
Branches to build: \*/master
Library Path: libraries
```
### Job Configuration
**simple-test-app → Configure → Build Configuration**
```
Mode: Jenkins Templating Engine
Advanced:
Pipeline Template Path: (empty or various values tried)
Pipeline Configuration Path: pipeline_config.groovy
Exclude branches without a pipeline configuration file
```
### Application Configuration
**File: simple-test-app/pipeline_config.groovy**
```groovy
template = “static-docker-ecr”
libraries {
docker {
image = "simple-test-app"
tag = "${env.BRANCH_NAME ?: 'main'}-${env.BUILD_NUMBER ?: 'latest'}"
}
ecr {
registry = "YOUR_AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com"
repository = "simple-test-app"
region = "us-east-1"
tag = "${env.BRANCH_NAME ?: 'main'}-${env.BUILD_NUMBER ?: 'latest'}"
image = "simple-test-app"
}
}
```
### Template File
**File: jte-library-repo/templates/Jenkinsfile**
```groovy
// JTE Default Template
// Executed as a JTE template with full library access
node {
stage("Checkout") {
checkout scm
}
stage("Docker Build") {
docker.buildImage() // FAILS HERE WITH MissingPropertyException
}
stage("Push to ECR") {
ecr.push()
}
}
```
### Library Step
**File: jte-library-repo/libraries/docker/steps/buildImage.groovy**
```groovy
void call() {
echo "\[Docker\] Building image: ${config.image}:${config.tag}"
sh """
docker build -t ${config.image}:${config.tag} .
"""
echo "\[Docker\] Image built successfully: ${config.image}:${config.tag}"
}
```
## Actual Build Output
```
Started by user Srikanth Mamidala
[JTE] templates/pipeline_config.groovy does not exist.
[JTE] – scm: git https://your-company.visualstudio.com/DefaultCollection/YOUR_ORG/_git/jte-library-repo
[JTE] Obtained Template Configuration File
[JTE] – scm: git Azure DevOps Services | Sign In
[JTE] – file path: pipeline_config.groovy
[JTE] Pipeline Configuration Modifications
[JTE] Configurations Added:
[JTE] - template set to static-docker-ecr
[JTE] - libraries.docker.image set to simple-test-app
[JTE] - libraries.docker.tag set to controller-53
[JTE] - libraries.ecr.registry set to YOUR_AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com
[JTE] - libraries.ecr.repository set to simple-test-app
[JTE] - libraries.ecr.region set to us-east-1
[JTE] - libraries.ecr.tag set to controller-53
[JTE] - libraries.ecr.image set to simple-test-app
[JTE] Obtained Template
[JTE] – scm: git https://your-company.visualstudio.com/DefaultCollection/YOUR_ORG/_git/jte-library-repo
[JTE] – file path: templates/Jenkinsfile
[JTE] Loading Library docker ✓
[JTE] – scm: git https://your-company.visualstudio.com/DefaultCollection/YOUR_ORG/_git/jte-library-repo
[JTE] Loading Library ecr ✓
[JTE] – scm: git https://your-company.visualstudio.com/DefaultCollection/YOUR_ORG/_git/jte-library-repo
[Pipeline] Start of Pipeline
[Pipeline] node
Running on platform-linux-static-pod-eks in /home/jenkins/agent/workspace/simple-test-app_controller
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Checkout)
[Pipeline] checkout
✓ Checkout successful
[Pipeline] }
[Pipeline] // stage
[Pipeline] stage
[Pipeline] { (Docker Build)
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
ERROR: groovy.lang.MissingPropertyException: No such property: docker for class: WorkflowScript
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:66)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.getProperty(ScriptBytecodeAdapter.java:471)
\[... stack trace continues ...\]
Finished: FAILURE
```
## The Issue
**Contradiction in behavior:**
-
Logs show: `[JTE] Loading Library docker` and `[JTE] Loading Library ecr`
-
Libraries successfully loaded from jte-library-repo repository
-
Library step files exist and are accessible
- ✗ Template execution fails: `No such property: docker for class: WorkflowScript`
- ✗ Library objects (docker, ecr) are not accessible in template
## What We’ve Tried
### 1. Multiple Template Approaches
**Subdirectories with Named Templates:**
```
templates/
├── static-docker-ecr/Jenkinsfile
└── node-docker-ecr/Jenkinsfile
```
With `template = “static-docker-ecr”` in pipeline_config.groovy.
-
JTE couldn’t find templates at this path
- Pipeline Template Path field in job config appears mandatory but ignores these values
**Dispatcher/Router Pattern:**
Created `templates/Jenkinsfile` as a router:
```groovy
def templateName = pipelineConfig.template
def templatePath = “templates/${templateName}/Jenkinsfile”
node {
checkout(\[
$class: 'GitSCM',
branches: \[\[name: '\*/master'\]\],
userRemoteConfigs: \[\[url: 'https://...jte-library-repo'\]\]
\])
load(templatePath)
}
```
-
Router loaded successfully
-
When using `load()`, the loaded template lost access to JTE library bindings
- Error: `No such property: docker` even though libraries loaded
**Single Default Template:**
Simplified to single `templates/Jenkinsfile`:
```groovy
node {
stage("Checkout") { checkout scm }
stage("Docker Build") { docker.buildImage() }
}
```
-
Template found and loaded
-
Libraries load: `[JTE] Loading Library docker`
-
Still fails: `No such property: docker`
### 2. Job Configuration Variations
**Pipeline Template Path Field:**
The job configuration field “Pipeline Template Path” appears mandatory (won’t accept empty value). Tried:
- `templates/Jenkinsfile` ![]()
- `Jenkinsfile` ![]()
- `static-docker-ecr/Jenkinsfile` ![]()
- `${template}` (variable substitution) ![]()
- Leaving empty (Jenkins fills with default) ![]()
None resolved the library binding issue.
### 3. Configuration Directory Variations
**Global Configuration Base Directory:**
- `templates`
(finds templates)
- Empty/blank
(templates not found)
- Root level `/`
(templates not found)
**Template Locations:**
- `Jenkinsfile` at repository root
(executes as regular pipeline, no JTE bindings)
- `templates/Jenkinsfile`
(finds template but libraries not accessible)
- `templates/subdirectory/Jenkinsfile`
(template not found by default)
### 4. Library Configuration
-
Verified library path: `libraries/docker/steps/buildImage.groovy`
-
Confirmed libraries load in build logs
-
Tried different library structures (flat vs nested)
-
Removed global pipeline_config.groovy (was initially blocking library loading)
-
Libraries show as loaded but remain inaccessible in template execution
### 5. Template Execution Context
-
Added `node` blocks (required for workspace)
-
Verified template loads from correct repository
-
Confirmed logs show: `[JTE] Obtained Template: templates/Jenkinsfile`
-
Library objects still not accessible despite successful loading
**The Core Issue:** Libraries consistently load successfully (confirmed in logs) but the binding that makes them accessible as objects (`docker`, `ecr`) in templates never materializes. This suggests either a configuration we’re missing or a bug in how JTE provides library bindings to template execution context.
## Questions
### 1. Library Binding Issue
Why do libraries load successfully (confirmed in logs) but aren’t accessible as objects in the template execution context?
**Expected:**
```groovy
docker.buildImage() // Should work after [JTE] Loading Library docker
```
**Actual:**
```
MissingPropertyException: No such property: docker
```
### 2. Multiple Templates Support
What is the correct way to support multiple named templates in a single governance tier?
We want applications to select templates via:
```groovy
template = “static-docker-ecr” // or “node-docker-ecr”
```
But JTE appears to only find default template at `templates/Jenkinsfile`.
### 3. Correct Template Structure
Should templates be:
- `templates/template-name/Jenkinsfile` (subdirectories)
- `templates/template-name.Jenkinsfile` (flat files)
- Something else?
### 4. Library Object Access
Should library objects be directly accessible in templates as `docker.buildImage()` or is there a different calling convention required?
## Goal
Enterprise setup with:
- Centralized governance (jte-library-repo)
- Multiple templates for different app types
- Shared, reusable libraries
- Applications select templates via pipeline_config.groovy
## Additional Context
- Using Multibranch Pipeline jobs
- JTE mode enabled in job configuration
- Libraries load in logs but binding not available during template execution
- Issue occurs with both Azure DevOps and GitHub
- This is a fundamental JTE configuration issue, not platform-specific
Any guidance on proper configuration for this setup would be greatly appreciated!
Jenkins setup: