It'll tell you there's a problem in function x and actually the problem is 4 functions down the stack. It's nuts, it's shit.
Just the other day, I don't know if serious or not, I read the Phoenix framework's author say I solve 100% of my dialyzer issues by not using dialyzer on Slack.
I've seen at least a few dozen bugs caught in development over the last few years caught by Dialyzer.
There could be many reasons for the sending code to be outside your analysis set. The sending code could be in another distinct code module (perhaps in a 3rd party library). The sending node may be running an older version of the code. The sending node may be running a newer version of the code. Something terrible could have happened on the sending node.
However, you can strongly type your way from "string of bytes" all the way to "a Pet record" by parsing, and the calling side just receives a strongly typed result on the lines of "Result<Pet, Error>".
Why couldn't you do the same thing in BEAM?
Sometimes one thing is the right thing to do and sometimes the other. But messages are such a low level concept in erlang... It's really hard to make a strongly typed system that doesn't pick one over the other, which is going to be the wrong answer half the time.
I'm not saying it can't be done, but many have tried and no one has succeeded yet.
Or at least, that’s how it works in the statically typed language Elm, which guarantees that your compiled code will not throw any runtime errors.