DEV Community

Cover image for set -e Will Kill Your Script For No Good Reason
Schiff Heimlich
Schiff Heimlich

Posted on

set -e Will Kill Your Script For No Good Reason

set -e Will Kill Your Script For No Good Reason

You add set -e to your bash script because you want it to stop on errors. Reasonable expectation. What could go wrong?

Plenty.

The Problem

set -e makes your script exit immediately when any command returns non-zero. Sounds fine until you remember how many things legitimately return non-zero:

grep -q "pattern" file    # returns 1 when no match found
curl -s https://example.com  # returns non-zero on 4xx/5xx
(( counter > 5 ))          # returns 1 when false
Enter fullscreen mode Exit fullscreen mode

None of those are errors. But set -e doesn't care.

Real Example

#!/bin/bash
set -e

# This fails silently when the string isn't found
name=$(grep "^username=" /etc/app/config | cut -d= -f2)

# This fails when count is zero  
if (( count > 0 )); then
    process_items
fi
Enter fullscreen mode Exit fullscreen mode

The grep returns 1 when there's no match. set -e kills the script. Same with arithmetic that's false.

The Workarounds

Option 1: Disable locally

set -e
grep -q "pattern" file || true   # always succeeds
Enter fullscreen mode Exit fullscreen mode

Option 2: Toggle around suspect code

set +e
grep -q "pattern" file
result=$?
set -e
Enter fullscreen mode Exit fullscreen mode

Option 3: Check explicitly

if grep -q "pattern" file; then
    name=$(grep "^username=" /etc/app/config | cut -d= -f2)
fi
Enter fullscreen mode Exit fullscreen mode

The Smarter Default

Skip set -e entirely. Check your commands explicitly:

if ! grep -q "pattern" file; then
    echo "pattern not found" >&2
    exit 1
fi
Enter fullscreen mode Exit fullscreen mode

More verbose, but you control exactly what fails and why.

Why This Bites You At 3am

Because the script worked for months, then one day curl starts returning 404 for a URL that moved, and your whole deploy stops. The actual failure is trivial, but set -e treats it like the world ended.

It's not your logic that's broken. It's set -e being overprotective.


This isn't a reason to never use set -e. Just don't use it without understanding what it actually checks. Most shell script bugs I debug come down to this flag surprising someone at the worst moment.

Top comments (0)