$? it's 0 ... in order to correctly catch it I must use set: [pipefail]. ignore_error: true. ignore_error is not actually ignoring anything - it is instead overriding the exit code to be 0 instead of 16. More appropriate name should have been override_error ${PIPESTATUS[0]} (${pipestatus[1]} in zsh):set it outputs nothing...pipefail and $? work as intended without having to ignore any errors or break the execution.