Why can restarting the Jenkins controller mid-pipeline be risky, and how does Jenkins try to handle it gracefully?
Quick Answer
Jenkins pipelines execute as Groovy code that's transformed into Continuation-Passing Style (CPS) so their execution state can be checkpointed to disk, allowing a Pipeline to survive a controller restart and resume where it left off — but this only works cleanly for pipeline steps that are properly CPS-transformed and durable; certain constructs (particularly inside script{} blocks calling non-whitelisted or non-serializable code) can fail to resume correctly, and any build actively mid-step (like a shell command running on an agent) at the exact moment of restart is inherently at risk of being left in an inconsistent state.
Detailed Answer
Jenkins Pipeline's execution engine transforms Groovy pipeline code using CPS specifically so that at any point between steps, the entire execution state (which stage you're in, local variables, etc.) can be serialized to disk. This is what allows a long-running pipeline to survive a Jenkins controller restart (planned maintenance, crash, upgrade) and resume from its last checkpoint rather than starting over or failing outright — a meaningful durability property for pipelines that can run for hours.
However, this durability has real limits: code that isn't properly whitelisted/serializable (certain non-CPS-transformed method calls, especially some patterns inside script { } blocks calling arbitrary Groovy or Java libraries) can fail to serialize correctly, causing a resumed pipeline to error out with a NotSerializableException or similar rather than resuming cleanly. And a build that's actively executing a step ON AN AGENT at the exact instant the controller restarts (e.g. a shell command mid-execution) is in a genuinely ambiguous state — the agent-side process may complete independently, but the controller's ability to correctly reconcile that outcome with its resumed pipeline state depends on the specific step and plugin behavior.
Operationally, this means: avoid unnecessarily complex non-serializable logic inside script{} blocks if pipeline durability across restarts matters for your use case, schedule Jenkins controller restarts/upgrades for low-build-volume windows where practical, and treat 'did all in-flight pipelines resume correctly' as something to explicitly verify after any controller restart in a busy CI environment, not just assume.
Interview Tip
Naming 'CPS transformation' and 'NotSerializableException' specifically signals you've actually hit and debugged this, versus just knowing pipelines 'can resume' abstractly.