Invisible characters in code, and the errors that make no sense

What goes wrong

A variable is undefined even though you can see it defined two lines above. A test comparing two identical-looking strings fails. A diff marks a line as changed and shows you the same line twice. Each of these has the same cause and none of them look like it.

Pasting. A snippet copied from a chat reply, a Stack Overflow answer or a rendered document brings characters that the compiler treats as significant and your editor renders as nothing. A zero-width space inside an identifier makes it a different identifier. A no-break space where you expect an ASCII space defeats a split. A curly apostrophe in a string literal is either a syntax error or, worse, a silently different string. A byte order mark at the top of a JSON file makes it fail to parse, pointing at a character you cannot see.

What to do about it

Get the characters out at the clipboard rather than hunting them later. Failing that, learn the census: pipe a file through a hex dump and look for e2 80 8b, c2 a0 and ef bb bf, which covers most of what actually bites. Configure your editor to reveal invisible characters, and consider a lint rule that rejects non-ASCII in identifiers.

Questions

Which one causes the compiler error that names a variable that looks right?

Almost always a zero-width space or a joiner inside the identifier. The name you see and the name the compiler sees differ by a character with no width.

Is there a security angle?

Yes. Bidirectional overrides can make source code display in an order different from the order it is stored in, so a reviewer reads one thing and the compiler compiles another. That technique has a name and a CVE history.