*Note: `zsh` will complain about "bad patterns" if you don't configure it to accept "inline comments" for most of the examples here and don't run them through a proxy shell as I have done with `sh <<-\CMD`.*

Ok, so, as I stated in the comments above, I don't know specifically about *bash's `set -E`*, but I know that POSIX compatible shells provide a simple means of testing a value if you desire it:

 sh -evx <<-\CMD
 _test() { echo $( ${empty:?error string} ) &&\
 echo "echo still works" 
 }
 _test && echo "_test doesnt fail"
 # END
 CMD
 sh: line 1: empty: error string
 + echo
 
 + echo 'echo still works'
 echo still works
 + echo '_test doesnt fail'
 _test doesnt fail

Above you'll see that though I used *`parameter expansion`* to test *`${empty?} _test()`* still *`return`s* a pass - as is evinced in the last *`echo`* This occurs because the failed value kills the *`$( command substitution )`* subshell that contains it, but its parent shell - *`_test`* at this time - keeps on trucking. And *`echo`* doesn't care - it's plenty happy to serve only a *`\newline; echo`* is ***not*** a test. 

But consider this:

 sh -evx <<-\CMD
 _test() { echo $( ${empty:?error string} ) &&\
 echo "echo still works" ; } 2<<-INIT
 ${empty?function doesnt run}
 INIT
 _test ||\
 echo "this doesnt even print"
 # END
 CMD
 _test+ sh: line 1: empty: function doesnt run

Because I fed *`_test()'s`* input with a pre-evaluated parameter in the *`INIT here-document`* now the *`_test()`* function doesn't even attempt to run at all. What's more the *`sh`* shell apparently gives up the ghost entirely and *`echo "this doesnt even print"` **doesn't even print.***

Probably that is ***not*** what you want.

This happens because the *`${var?}`* style parameter-expansion is ***designed to quit the `shell`*** in the event of a missing parameter, it [works like this][1]:

> ***`${parameter:?[word]}`***

>> Indicate Error if **`Null`** or **`Unset.`** If parameter is unset or null, the *`expansion of word`* (or a message indicating it is unset if word is omitted) shall be *`written to standard error`* and the ***`shell exits with a non-zero exit status`.*** Otherwise, the value of *`parameter shall be substituted`.* An interactive shell need not exit.

I won't copy/paste the entire document, but if you want a failure for a **`set but null`** value you use the form: 

> *`${var` **:?** `error message }`*

With the *`:colon`* as above. If you want a *`null`* value to succeed, just omit the colon. You can also negate it and fail only for set values, as I'll show in a moment.

Another run of *`_test():`*

 sh <<-\CMD
 _test() { echo $( ${empty:?error string} ) &&\
 echo "echo still works" ; } 2<<-INIT
 ${empty?function doesnt run}
 INIT
 echo "this runs" |\
 ( _test ; echo "this doesnt" ) ||\
 echo "now it prints"
 # END
 CMD
 this runs
 sh: line 1: empty: function doesnt run
 now it prints

This works with all kinds of quick tests, but above you'll see that *`_test()`*, run from the middle of the *`pipeline`* fails, and in fact its containing *`command list`* subshell fails entirely, as none of the commands within the function run nor the following *`echo`* run at all, though it is also shown that it can easily be tested because *`echo "now it prints"` **now prints.*** 

The devil is in the details, I guess. In the above case, the shell that exits is *not* the script's *`_main | logic | pipeline`* but the ***`( subshell in which we ${test?} ) ||`*** so a little sandboxing is called for.
 
And it may not be obvious, but if you wanted to only pass for the opposite case, or only *`set=`* values, it's fairly simple as well:

 sh <<-\CMD
 N= #N is NULL
 _test=$N #_test is also NULL and
 v="something you would rather do without" 
 ( #this subshell dies
 echo "v is ${v+set}: and its value is ${v:+not NULL}"
 echo "So this ${_test:-"\$_test:= will equal ${_test:="$v"}"}"
 ${_test:+${N:?so you test for it with a little nesting}} : &&\
 echo "sure wish we could do some other things"
 )
 ( #this subshell does some other things 
 unset v #to ensure it is definitely unset
 echo "But here v is ${v-unset}: ${v:+you certainly wont see this}"
 echo "So this ${_test:-"\$_test:= will equal ${_test:="$v"}NULL"}"
 : ${_test:+${N:?is never substituted}} &&\
 echo "so now we can do some other things" 
 )
 # END
 CMD
 v is set: and its value is not NULL
 So this $_test:= will equal something you would rather do without
 sh: line 6: N: so you test for it with a little nesting
 But here v is unset:
 So this $_test:= will equal NULL
 so now we can do some other things

The above example takes advantage of all 4 forms of POSIX parameter substitution and their various *`:colon null`* or *`not null`* tests. There is more information in the link above, and [here it is again][1]. 

And I guess we should show our ***`_test`*** function work, too, right? We just declare ***`empty=something`*** as a parameter to our function (or any time beforehand):

 sh <<-\CMD
 _test() { echo $( echo ${empty:?error string} ) &&\
 echo "echo still works" ; } 2<<-INIT
 ${empty?tested as a pass before function runs}
 INIT
 echo "this runs" >&2 |\
 ( empty=not_empty _test ; echo "yay! I print now!" ) ||\
 echo "suspiciously quiet"
 # END
 CMD
 this runs
 not_empty
 echo still works
 yay! I print now!

It should be noted that this evaluation stands alone - it requires no additional test to fail. A couple more examples:

 sh <<-\CMD
 empty= 
 ${empty?null, no colon, no failure}
 unset empty
 echo "${empty?this is stderr} this is not"
 # END
 CMD
 sh: line 3: empty: this is stderr

 sh <<-\CMD
 _input_fn() { set -- "$@" #redundant
 echo ${*?WHERES MY DATA?}
 #echo is not necessary though
 shift #sure hope we have more than $1 parameter
 : ${*?WHERES MY DATA?} #: do nothing, gracefully
 }
 _input_fn heres some stuff
 _input_fn one #here
 # shell dies - third try doesnt run
 _input_fn you there?
 # END
 CMD
 heres some stuff
 one
 sh: line :5 *: WHERES MY DATA?

 [1]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02