Jenkins pipeline java.io.NotSerializableException java.util.regex.Matcher error even with @NonCPS

Probably due to the m variable scope. Try restrict it with def like this:

def m = (logLine =~ TEST_LOGLINE_END_REGEX)

Without def a variable is created in a global script binding and hence still exists after exiting from the method.


Jenkins require all variables to be serializable because the state of the pipeline is periodically saved to disk in case of interrupts like a server restarts. This feature allows pipelines to maintain their state and continue even after the server is restarted. Variables of type Matcher are not serializable and require some additional work by the developer.

From jenkinsci/pipeline-plugin Serializing Local Variables:

However the safest approach is to isolate use of nonserializable state inside a method marked with the annotation @NonCPS. Such a method will be treated as “native” by the Pipeline engine, and its local variables never saved.

The code example provided:

@NonCPS
def version(text) {
  def matcher = text =~ '<version>(.+)</version>'
  matcher ? matcher[0][1] : null
}

Additional material backing this can be found on Pipeline Groovy Plugin Technical Design, here they discuss more technical details and behavior of methods marked with @NonCPS.

Pipeline scripts may mark designated methods with the annotation @NonCPS. These are then compiled normally (except for sandbox security checks), and so behave much like “binary” methods from the Java Platform, Groovy runtime, or Jenkins core or plugin code. @NonCPS methods may safely use non-Serializable objects as local variables, though they should not accept nonserializable parameters or return or store nonserializable values. You may not call regular (CPS-transformed) methods, or Pipeline steps, from a @NonCPS method, so they are best used for performing some calculations before passing a summary back to the main script. Note in particular that @Overrides of methods defined in binary classes, such as Object.toString(), should in general be marked @NonCPS since it will commonly be binary code calling them.

See: Serializing Local Variables and Pipeline Groovy Plugin Technical Design


Just for clarity, the following worked for me.

The extra work for the developer, as an example, see the code below.

my.Parameter is NOT Serializable

so I make a method, without a def and annotate it @NonCPS and call that from the node block

  node('MySys') {
    echo 'hello'
    avoidCPS()
    echo 'finished'
  }

  @NonCPS
  avoidCPS () {
    // use my.Parameter here
    my.Parameter p = new my.Parameter()
    ... do some more ...
  }