Unfortunately, for now, I think the only way is to use try catch in a script block and re-throw the error after performing the error handling. See example below:
pipeline {
agent any
stages {
stage('1') {
steps {
sh 'exit 0'
}
}
stage('2') {
steps {
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
script {
try {
sh "exit 1"
} catch (e) {
echo 'send email'
throw e
}
}
}
}
}
stage('3') {
steps {
sh 'exit 0'
}
}
}
}
Answer from Erik B on Stack OverflowJenkins: Ignore failure in pipeline build step - Stack Overflow
Jenkins: Aborting a build with a catchError() - Stack Overflow
check on github says ok while stage failed on jenkins (using catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') in Jenkinsfile)
groovy - Try-catch block in Jenkins pipeline script - Stack Overflow
Videos
and how would I print it or see it? For some reason any log line printing this error out in the groovy projects I am inheriting prints a dogshit stacktrace. Yes I used the technical term. At work of course the plugin has to be in action to be used so there is no stepping through like I am used to coming from a java dev background. So is there a doc, online resource or maybe simple tutorial I could go through on my own to simulate this and play around to better my understanding?
pseudocode of the instance I mean just to be clear:
try{
//some code that fails
}catch(error){
logger.error(error);
}
Edit: clearing up my gripe: the logged error will have the line number for the logger.error() line and not the line the error occurred on?
It's the java/groovy Exception object. Try error.message for a brief trace.
For this, check out the Jenkins Java API Documentation. You can find the available methods of the Exception class. Also, depending on what kind of build job you're using, you can find that class as well, find the inherited classes and nested objects, and follow the documentation to see specific Exceptions that get thrown.
To ignore a failed step in declarative pipeline you basically have two options:
- Use
scriptstep andtry-catchblock (similar to previous proposition by R_K but in declarative style)
stage('someStage') { steps { script { try { build job: 'system-check-flow' } catch (err) { echo err.getMessage() } } echo currentBuild.result } }
- Use
catchError
stage('someStage') { steps { catchError { build job: 'system-check-flow' } echo currentBuild.result } }
In both cases the build won't be aborted upon exception in build job: 'system-check-flow'. In both cases the echo step (and any other following) will be executed.
But there's one important difference between these two options. In first case if the try section raises an exception the overall build status won't be changed (so echo currentBuild.result => SUCCESS). In the second case you overall build will fail (so echo currentBuild.result => FAILURE).
This is important, because you can always fail the overall build in first case (by setting currentBuild.result = 'FAILURE') but you can't repair build in second option (currentBuild.result = 'SUCCESS' won't work).
In addition to simply making the stage pass, it is now also possible to fail the stage, but continue the pipeline and pass the build:
pipeline {
agent any
stages {
stage('1') {
steps {
sh 'exit 0'
}
}
stage('2') {
steps {
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
sh "exit 1"
}
}
}
stage('3') {
steps {
sh 'exit 0'
}
}
}
}
In the example above, all stages will execute, the pipeline will be successful, but stage 2 will show as failed:

As you might have guessed, you can freely choose the buildResult and stageResult, in case you want it to be unstable or anything else. You can even fail the build and continue the execution of the pipeline.
Just make sure your Jenkins is up to date, since this feature is only available since "Pipeline: Basic Steps" 2.16 (May 14, 2019). Before that, catchError is still available but without parameters:
steps {
catchError {
sh "exit 1"
}
}
This is addressed in the official documentation, which provides two suggestions: the Pipeline step catchError { } and the native Groovy try-catch-finally syntax for handling exceptions.
Since it sounds like you may want your code to repeat on many different nodes, another option may be to put your nodes into parallel blocks. A failure in one parallel branch will not halt execution in any of the other parallel branches.
When a Jenkins stage fails, all of the rest starts and ignore message. So stages are skipped but you really want them to run. You can use the catchError block to catch errors and continue with the pipeline. Here’s an example:
stage('Example') {
steps {
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
sh './run-my-script.sh'
}
}
}
This worked for me by setting catchInterruptions to false:
catchError(buildResult: 'UNSTABLE', stageResult: 'UNSTABLE', catchInterruptions: false) {
// Do some stuff here and continue the build if anything fails
}
Now, all stages are aborted with one click when we abort a build. Where previously, we would have to abort each stage individually.
I was just being stupid and misunderstanding the documentation. I just needed to set the catchInterruptions option to true (which is the default value).
catchError(buildResult: 'UNSTABLE', stageResult: 'UNSTABLE', catchInterruptions: true) {
// Do some stuff here and continue the build if anything fails
}
OR (because true is the default value)
catchError(buildResult: 'UNSTABLE', stageResult: 'UNSTABLE') {
// Do some stuff here and continue the build if anything fails
}
try like this (no pun intended btw)
script {
try {
sh 'do your stuff'
} catch (Exception e) {
echo 'Exception occurred: ' + e.toString()
sh 'Handle the exception!'
}
}
The key is to put try...catch in a script block in declarative pipeline syntax. Then it will work. This might be useful if you want to say continue pipeline execution despite failure (eg: test failed, still you need reports..)
You're using the declarative style of specifying your pipeline, so you must not use try/catch blocks (which are for Scripted Pipelines), but the post section. See: https://jenkins.io/doc/book/pipeline/syntax/#post-conditions