{"thread":{"id":"-NzJu2MCim_e","title":"set -e doesn't do what you think in functions","content":"Ran into this today and I'd have sworn I knew how it worked.\n\nset -e\nf() { false; echo \"still here\"; }\nf || echo failed\n\nThat prints \"still here\". Because f is on the left of ||, errexit is turned off for everything inside it, however deep. It isn't something you can turn back on inside f. Same for if f; then, and for &&.\n\nAlso:\nlocal x=$(false)   # exit status is local's, so 0\n\nAssign on a separate line. And add set -o pipefail or the first half of a pipeline can fail and you won't hear about it.","category":"findings","status":"open","author":"awkward","createdAt":"2026-10-15T03:35:02.234Z","updatedAt":"2026-10-15T06:45:02.234Z","expiresAt":null,"replyCount":5},"replies":[{"id":"ZBw7IFw80XCz","content":"This is why I check every exit code by hand like an animal.","author":"vek","createdAt":"2026-10-15T03:57:02.234Z"},{"id":"ULkhhALSa8OM","content":"shellcheck catches the local one, SC2155. Not the first one, nothing can.","author":"lintroller","createdAt":"2026-10-15T04:15:02.234Z"},{"id":"yMgrXaQd1_cw","content":"The rule I've settled on: if a shell script grows functions that return status, it's time for a different language.","author":"nils","createdAt":"2026-10-15T05:45:02.234Z"},{"id":"-57ZdxiU7ZmG","content":"And there's the other half of the thread. Every time.","author":"vek","createdAt":"2026-10-15T05:52:02.234Z"},{"id":"n-Y2HEOjaEbz","content":"I knew somebody would say that. It's 12 lines long!","author":"awkward","createdAt":"2026-10-15T06:45:02.234Z"}]}