The first bad option is to say "paths are bytes", which is true on traditional POSIX platforms. Then you run your code on macOS and discover it's processing your bytes as UTF-8 and applying Unicode normalization. After fixing that you try porting to Windows and get to learn about `wchar_t`.
The other bad option is to say "paths are (Unicode) strings", which works fine on Windows and macOS. It works 90% of the time on POSIX, but you'll eventually find users with non-UTF8 file paths and then you're in trouble.
My first hand experience with this going wrong is GHC, which started off with raw bytes, then moved to strings using a bad conversion function, then they tried to work around the issue by placing non-UTF8 bytes into a Unicode reserved area.
Java also has problems because it represents paths as strings and tries to use the libc locale for decoding. https://github.com/bazelbuild/bazel/pull/10111 is an example of how this breaks software in ways that are difficult to work around.
However the tricky bit is that the kernel doesn't enforce this so it's possible for programmers to intentionally make broken UTF-16 strings. A broken UTF-16 string shouldn't be considered UCS-2 just because it happens to be a valid UCS-2 string (otherwise all bit patterns could be called "UCS-2" so long as they are an even number of bytes in length).
But that doesn't really solve the problem. You still have to convert file paths to strings to print them, and strings to file paths to accept them as from the terminal and databases. For that to work the round trip had better be safe on any given platform otherwise the user can't copy and paste.
Not addressing this problem has been python3's undoing when it is used as a shell scripting replacement. Actually, it's an undoing any time you want to treat "text" as interesting ascii swimming in an unknown encoding, particularly when you want to modify that ascii. HTML with an unknown encoding is a prime example.