I used to like passing errors up the stack like you describe, but this invariably leads to hard-to-debug programs that terminate with unspecific errors like "i/o error", leaving it to the user or developer to figure out in which exact branch of the 9-layer call stack that error originated. If your error handling is exception-based and if your interpreter/runtime generates tracebacks you can do that, but not if you explicitly handle errors within the regular control flow.