Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

exit 0 means the command or operation whose status was checked reported success according to its own rules. It does not prove that every earlier command succeeded—or that the artifact, test report, or deployment you wanted actually exists. To find a misleading success, trace which status reaches the shell or CI runner, then make failures propagate explicitly.

What does exit 0 actually tell you?

At an observed command boundary, a zero exit status is a success report from that command or operation. It is not a retrospective audit of every command that ran before it. A shell can select a status for a command list or pipeline, and a CI runner can report the status it receives from a script item or combined command string. Those boundaries can hide a failure that occurred earlier.

POSIX defines shell status behavior for command lists and pipelines; Bash documents its own rules, including the optional pipefail setting. GitLab documents CI cases where a prior failure is not reflected in the job result. The practical debugging question is therefore: which command’s status did the shell or runner actually observe?

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How can a failed command disappear from a command list?

An && list does not automatically mean that every failure will make the overall CI job fail in the way you expect. GitLab documents an example with invalid commands joined by && where the job can still be reported successful; its documented workaround is to group the line in parentheses so failure propagates. The result depends on the full command list and how the runner handles it.

For example, when debugging a CI script, do not infer the job outcome just by noticing an && between commands. Check the complete script item and runner behavior, and use the grouping approach GitLab documents when it fits that context:

(first-command && second-command)

Grouping is a GitLab-documented remedy for its example, not a universal substitute for understanding the active shell and runner.

How can a later command overwrite an earlier failure?

When several commands are placed in one CI command string, GitLab says only the final command’s success or failure is reported; an earlier failure can be ignored. For instance, if a build command fails and a later cleanup command succeeds, the final status may describe cleanup rather than the build.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

GitLab documents two approaches to preserve the failure signal:

  • Put commands in separate script items so the runner can handle each command’s status separately.
  • Explicitly propagate failure within the combined command string, rather than letting a later successful command become the reported result.

GitLab summarizes the rule in its Scripts and job logs documentation: “If multiple commands are combined into one command string, only the last command’s failure or success is reported.”

Why can a pipeline succeed when an upstream command fails?

A pipeline has its own status-selection rules. In a shell where the pipeline status defaults to the final command’s status, a pipeline such as missing-tool | cat can report success if cat succeeds, even though the command on the left failed to run. POSIX and Bash both specify pipeline behavior, but their rules should not be treated as interchangeable.

In Bash specifically, enable pipefail when the pipeline should fail if a command in it fails:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
set -o pipefail
missing-tool | cat

Bash’s pipefail option changes how a pipeline’s status is determined. Confirm that the script actually runs under Bash before relying on it; another shell may not support the same option or semantics. Consult the POSIX shell specification and the Bash manual for the rules that apply to your shell.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Compare the three ways success can be misleading

Pattern Where the reported status is selected Failure that can be lost Visibility fix
Commands joined with && The full command list and CI runner handling A failure within the list may not make the job fail as expected For GitLab’s documented example, group the line in parentheses; verify the shell and runner behavior.
Several commands in one CI command string The combined command string’s final command, as reported by GitLab An earlier command’s failure Use separate script items or explicitly propagate failure.
Pipeline The shell’s pipeline-status rule An upstream command’s failure when the final command succeeds Use the appropriate shell-specific status mechanism; in Bash, consider set -o pipefail.

How to debug a success status that looks wrong

  1. Locate the boundary. Identify whether the status you are reading comes from an individual command, a shell list, a pipeline, or a CI wrapper.
  2. Trace the final status-producing operation. Check what command ran last in the relevant string or pipeline and which status the runner receives.
  3. Inspect the active shell and runner configuration. Confirm the shell used by the script and how the CI system executes each script item; do not assume Bash behavior in another shell.
  4. Make required failures visible. Separate CI commands, propagate failure explicitly, group the relevant GitLab command list, or use a shell-specific pipeline setting where appropriate.
  5. Verify the intended output independently. If success means an artifact was produced, a test report was written, or a deployment changed the target, check that result directly rather than treating exit status as proof of it.

The final check is a practical safeguard: command status reports what the observed operation said about itself, while the desired external result may need its own verification.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.