I think the issue here is the inconsistent behavior of read -t <num> when delim != '\n'.
read -t 3 -d <not-\n> will *not* leave the input as typeahead. read -t 3 -d $'\n' will leave the input as typeahead. I tried playing with the 'unbuffered_read' variable in builtins/read.def (forcing it to be 1 even for delim == '\n'), but it seems that the special behavior for '\n' is further down the code. Also, this is how ksh93 and zsh behave: ksh93 behaves consistently (delim == or != to '\n') | dualbus@hp ...local/src/bash % /bin/ksh93 -c "false; read -t 3" | afafafafafafa% | dualbus@hp ...local/src/bash % /bin/ksh93 -c "false; read -d d -t 3" | afafafafafafa% zsh ignores -t when a custom -d is in effect, does the same thing as bash when delim == '\n' | dualbus@hp ...local/src/bash % /bin/zsh -c "false; read -t 3" | afafafafafafafafa% | dualbus@hp ...local/src/bash % afafafafafafafafa<RET> | zsh: command not found: afafafafafafafafa | dualbus@hp ...local/src/bash % /bin/zsh -c "false; read -d d -t 3" | afafafafafafafa | | d%<had to type d, the timeout was not working> bash leaves the input in some buffer when delim == '\n' and the timeout is reached. It consumes the input when delim != '\n'. | dualbus@hp ...local/src/bash % /bin/bash -c "false; read -t 3" | afafafafafaf% | dualbus@hp ...local/src/bash % afafafafafaf<RET> | zsh: command not found: afafafafafaf | dualbus@hp ...local/src/bash % /bin/bash -c "false; read -d d -t 3" | afafafafafafafaf% | dualbus@hp ...local/src/bash %