Nowadays there's an option on the table for raising definitional errors, which could easily be turned into nulls with try third (...)
>> third [a b]
** Error: Cannot pick 3 of BLOCK! (or somesuch)
>> try third [a b]
== ~null~ ; anti
(I've mentioned that this is different from the limited design of Rebol's historical errors, e.g. if you said attempt [third [a b]] in an R3-Alpha or Red that errored, it would give null back...but so would attempt [thirrd [a b]] because the lack of definitional-ism means it couldn't discern errors arising from a direct call from typos or other downstream errors.)
For cases where you would have been trusting a THIRD that returns NULL to trigger downstream errors, this gives better error locality. e.g. append [a b c] third [d e] would blame the THIRD, not the append.
And for cases where you might not be able to trust that NULL wouldn't be interpreted as an error downstream, it would be more robust. Also you'd give readers a clue at the callsite when you actually were intending that the operation might fail by the presence of the TRY.
This comes down down to the behavior of PICK (since FIRST is a specialization of PICK). I was just thinking about that with respect to objects:
>> obj: make object! [x: 10]
>> pick obj 'x
== 10
>> pick obj 'y
** Error: y is not a field of object
>> try pick obj 'y
== ~null~ ; anti
If we raised a definitional error out of pick in this case, then you could try pick and get null. It would conflate with the case where the variable existed and actually held null. (But if that was an issue, you could use EXCEPT or another handler to handle the definitional error specifically.)
When you think about PICK in general beyond just the block case, it does seem like more uniformly giving an error which can be "softened" via TRY would be a good idea.