Problem Statement
Explain error handling strategies in Jenkins Pipeline. Include try-catch, error step, catchError, post conditions, and retry mechanisms.
Explanation
Try-catch blocks in script step or Scripted Pipeline handle exceptions:
```groovy
stage('Build') {
steps {
script {
try {
sh 'mvn clean package'
} catch (Exception e) {
echo "Build failed: ${e.message}"
currentBuild.result = 'FAILURE'
throw e // Rethrow to fail pipeline
}
}
}
}
```
Caught exceptions can be logged, notifications sent, or pipeline behavior modified. Rethrowing fails the pipeline while catching without rethrowing continues.
Error step explicitly fails pipeline with message:
```groovy
if (!fileExists('required-file.txt')) {
error 'Required file not found'
}
```
Error stops execution immediately failing the stage and pipeline.
CatchError wraps steps allowing pipeline to continue even if steps fail:
```groovy
stage('Optional Task') {
steps {
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
sh 'npm run optional-task' // Pipeline continues even if this fails
}
}
}
```
Parameters: buildResult (overall build result if error occurs), stageResult (stage result if error occurs), catchInterruptions (catch user abort). Useful for non-critical steps that shouldn't fail entire build.
Post conditions handle cleanup and notifications based on result:
```groovy
post {
failure {
echo 'Pipeline failed'
mail to: 'team@example.com',
subject: "Failed: ${env.JOB_NAME}",
body: "${env.BUILD_URL}"
}
unstable {
echo 'Tests failed but build succeeded'
}
always {
junit '**/target/test-results/*.xml'
cleanWs()
}
}
```
Always block runs regardless of result ensuring cleanup happens.
Retry mechanism automatically retries failed steps:
```groovy
stage('Flaky Test') {
steps {
retry(3) {
sh 'npm run flaky-test'
}
}
}
```
Retries up to 3 times before failing. Useful for flaky tests or transient network issues.
Timeout prevents hanging builds:
```groovy
stage('Long Running Task') {
steps {
timeout(time: 1, unit: 'HOURS') {
sh './long-task.sh'
}
}
}
```
Aborts step if exceeds timeout.
Combining strategies:
```groovy
stage('Deploy') {
steps {
script {
def maxRetries = 3
def retryCount = 0
def success = false
while (!success && retryCount < maxRetries) {
try {
timeout(time: 5, unit: 'MINUTES') {
sh './deploy.sh'
success = true
}
} catch (Exception e) {
retryCount++
if (retryCount >= maxRetries) {
error "Deployment failed after ${maxRetries} attempts: ${e.message}"
}
sleep(time: 30, unit: 'SECONDS')
echo "Retry ${retryCount}/${maxRetries} after error: ${e.message}"
}
}
}
}
}
```
CurrentBuild variable tracks build state:
```groovy
script {
currentBuild.result = 'UNSTABLE' // Set result
currentBuild.description = 'Custom description'
echo "Current result: ${currentBuild.result}"
}
```
Results: SUCCESS, UNSTABLE, FAILURE, ABORTED.
Best practices: use try-catch for expected errors requiring special handling, use catchError for optional steps, implement retry for transient failures, set timeouts preventing infinite hangs, use post conditions for cleanup ensuring it always runs, log errors with context for debugging, send notifications on failures, fail fast for critical errors, set meaningful build descriptions, avoid catching all exceptions unless necessary. Understanding error handling creates robust pipelines that gracefully handle failures and provide clear feedback.