Say a function has some return type Result. If our only error handling mechanism is Err(e) then were restricted to E representing the set of errors due to invalid arguments and state,
and the set of errors due to the program itself being implemented incorrectly.
In a good software architecture (imo) panics and other hard failure mechanisms are there for splitting E into E1 and E2, where E1 is the set of errors that can happen due to the caller screwing up and E2 being the set of errors that the caller screwed up. The caller shouldn't have to reason about the callee possibly being incorrect!
Functional programming doesn't really come into the discussion here - oftentimes this crops up in imperative or object oriented code where function signatures are lossy because code relies on side effects or state that the type system can't/won't capture (for example, a database or file persisted somewhere). Thats where you'll drop an assert or panic - not as a routine part of error handling.