Skip to content

fix: set -e incorrectly exits on [[ ]] && cmd inside { } > file #807

@chaliy

Description

@chaliy

Problem

Under set -e, a [[ condition ]] && command where the condition is false incorrectly causes script termination in certain contexts. Per POSIX/bash spec, set -e should NOT trigger on commands that are part of an AND-OR list.

Works correctly at the top level:

set -e
[[ "a" == "b" ]] && echo "match"
echo "reached"   # ✅ correctly reached

Fails inside functions:

set -e
f() {
    [[ "a" == "b" ]] && return 0
    echo "should reach here"
}
f   # ❌ exits with code 1

Fails inside brace groups with redirections:

set -e
x=""
{
    echo "line1"
    [[ -n "$x" ]] && echo "has value"
    echo "line2"
} > /tmp/out.txt   # ❌ exits with code 1

Fails inside for loops in functions:

set -e
f() {
    for x in a b c; do
        [[ "$x" == "b" ]] && return 0
    done
}
f   # ❌ exits with code 1 on first iteration (x="a")

Impact

Critical correctness bug. The [[ cond ]] && action pattern is one of the most common bash idioms. Combined with set -e (which most scripts use), this breaks:

  • Conditional printing: [[ -n "$var" ]] && echo "$var"
  • Early returns: [[ "$x" == "match" ]] && return 0
  • Guard clauses: [[ -f "$file" ]] && source "$file"

The wedow/ticket script is completely broken by this — it uses set -euo pipefail and this pattern throughout.

Root cause

The set -e check is likely being applied to the exit code of the [[ ]] test command itself rather than the exit code of the entire AND-list. When [[ cond ]] evaluates to false (exit 1), that exit code should be absorbed by the && operator, not propagated to set -e. This works correctly at the top level but breaks inside functions, brace groups, and for loops.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions