I wish it were that simple a case. Turns out there are other cases where a script that runs well in non-interactive move would crash when run with -i. In my case it was trap for TSTP. A workaround is to put ``setopt nomonitor``, which in my case is valid as I don't need job control. Though what is interesting is that the script ends with an error code of 0. Anyway the exit behavior itself is inconsitent. Try two experiments: 1) add ``trap 'foo=1' TSTP`` as first line of your sample code in this thread. This time zsh would complain but not exit. 2) add ``trap 'foo=1' TSTP`` to your function read-field() or in while loop. This time zsh will exit with error code 1. In my script, where the trap is somewhere in 3 or 4th level function in the stack, the script exits with exit code 0.
Here's the link to relevant part of code:
```
if (jobbing && (sig == SIGTTOU || sig == SIGTSTP || sig == SIGTTIN)) {
zerr("can't trap SIG%s in interactive shells", sigs[sig]);
return 1;
}
```
I figured ``setopt nomonitor`` disables jobbing, and bypasses executing that if block.