The superficial answer is that it's always been that way, and so everybody does it. [POSIX](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/file.html) states that

> If the file named by the file operand does not exist, cannot be read, or the type of the file named by the file operand cannot be determined, this shall not be considered an error that affects the exit status.

Unfortunately, no rationale is given, so the only obvious reason for why POSIX states that is historical practice.

The `file` utility first appeared in [Unix Research version 4](https://minnie.tuhs.org/cgi-bin/utree.pl?file=V4/man/man1/file.1) in 1973. At the time, standard utilities didn't check for errors (even though processes had had a return status since at least [version 3](https://www.tuhs.org/cgi-bin/utree.pl?file=V3/man/man2/exit.2) if not version 2). For example, `cat` started returning a nonzero status if a file did not exist only in [version 8](https://www.tuhs.org/cgi-bin/utree.pl?file=V8/usr/src/cmd/cat.c): [version 7](https://www.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/cat.c) just printed an error message and kept going. But even by [version 10](https://www.tuhs.org/cgi-bin/utree.pl?file=V10/cmd/file.c), `file` only exited with a nonzero status if it could not read the `magic` file, not if it could not read a data file.

A possible reason for `file` not to fail is that it isn't just interested in file contents, but also in files types, and it considers “does not exist” to be a special kind of file alongside directory, symbolic link, broken symbolic link, etc. This is a weak justification since an unreadable file is really not a special kind of file, it's a file whose nature cannot be determined, which is an error by any sensible measure. Also, it could apply to `ls`, which still did not return an error if given a nonexistent file name [as of version 10](https://www.tuhs.org/cgi-bin/utree.pl?file=V10/cmd/ls.c), but for which this eventually became universal practice.

So it seems that the return status of `file` is a mistake that time forgot. Now that there are probably scripts out there that rely on `file` not returning an error status if the file does not exist, it's too late to change.