Skip to content

Unraveling Git Exceptions in Jenkins Pipeline Scripts

In a recent encounter with my Jenkins pipeline, I faced an abrupt halt due to the hudson.AbortException, which was actually underneath several exceptions caused by issues within our git workflow triggered during checkout operations as per this error:

 hudson.plugins.git.GitException: Command "git fetch --tags...` returned status code 128 with a stderr message pointing to an issue creating the `.git/shallow.lock`: `fatal: Unable to create '/var/jenkins_home/workspace/some_project/.git/shallow.lock': File exists`.

While it’s uncommon for Jenkins pipelines, exception chaining (as explained in this Baeldung article) typically occurs when an error propagates through multiple layers of code execution; however, my goal was to specifically catch and handle GitException instead of the generic or parent exception like hudson.AbortException.

Here’s a solution I discovered that allows me to access not just the root cause but also retrieve messages from each caught Exception in our Java-based Jenkins pipeline script:

import org.jenkinsci.plugins.workflow.steps.StepContribution;
try {
    // Git fetching operation here...
} catch (Exception e) {    
    StepContribution source = new java.lang.Throwable().getCause(); 
      while(source instanceof javax.management.eas.InterruptedException){  
          Source=source=(StepContribution)((javax.management.eas.InterruptedException)(this)).getSuppressed();    
    }                      
         System.out.println("Caught exception: "+ source);            
        while(source instanceof java.lang.Exception){          
            if (source == null || ((java.lang.Exception)source).getMessage()==null ){   // No message in the chain, get out here!                      
                System.out.println("No more exceptions!");             
                break;        
            }     else {     
               Source =((javax.management.eas.InterruptedException)(this)).getSuppressed();          
             System.out.println(Source);   // Print message of exception in the chain                      
        } 
    }             
} catch (org.jenkinsci.plugins.workflow.steps.StepContribution c) {     
         java.lang.Exception cause = new org.jenkinsci.plugins.workflow.steps.exceptions.GitCheckoutFailed(c).getCause();   //Get the first exception in chain (usually hudson or jenkins itself.)    
       System.out.println("Root Exception: "+ c);   
}        

The script above iteratively traverses upward through each cause of exceptions, starting from e until it finds a non-null message and the root exception type (org.jenkinsci.plugins.workflow.steps.StepContribution). For Jenkins pipelines where you’re dealing with complex chains like this, extracting specifics about which part caused an issue becomes crucial for debugging purposes – in my case:

Caught Exception: org.codehaus.groovy.runtime.StackTraceUtils$ErrorHandlingFailedSentinel@573d9506[message=fatal: Unable to create '/var/jenkins_home/workspace/_Home/.git/shallow.lock': File exists]
Root Exception: org.codehaus.groovy.runtime.StackTraceUtils$ErrorHandlingFailedSentinel@14e38d56[message=fatal: Unable to create '/var0279bcea-some_project/.git/shallow.lock': File exists]

As I was dealing with a GitException, the root exception turned out not only included valuable information about my error but also helped me identify that the real culprit lay deeper within an interrupted Jenkins step, providing direction for further investigation and resolution of our Git checkout failure in pipeline execution. This approach gives insight into handling exceptions effectively by revealing layers upon which they’ve been built up over time – a handy trick when troubleshooting complex systems like those managed with Groovy-based pipelines on the CI server Jenkins!


Previous Post
Resolving Docker BuildKit ERROR on Ubuntu Install
Next Post
How to Use uriRegexRewrite in Istio VirtualServi