I don't think catching runtime errors here is the best approach. We never expect this to fail at runtime, only if the function is used the wrong way by a programmer. Will this not unnecessarily hide true bugs?
I think avoiding dead code makes sense, but I also like the function being self-contained and self-descriptive like this without too much overhead, so I guess overall I'm ~0 on the change.
As an alternative, how about instead of catching std::runtime_error&, we only call ParseSighashString if univalue is str? This way we make the assumptions explicit and self-documenting, too. Would also prefer adding a docstring to ParseSighasString documenting the input assumptions (potentially with "@pre"). As a public function, it's quite easy for a programmer to use this in the wrong way if not careful. I'm not too familiar with fuzzing best practices though, so maybe this has other (bigger) downsides?
try {
if (univalue.isNull() || univalue.isStr()) (void)ParseSighashString(univalue);
} catch (const UniValue&) {
}