Footguns are features or designs more likely to be misused, often leading to self-inflicted problems or bugs (“shooting yourself in the foot”). See a list of C functions banned in the git codebase for being footguns. Some more examples:
- Inconsistent naming
- Manual garbage collection for connections or open files
- Race conditions with async code
- Multiple sources of truth
- Long argument lists
- Shadowing variables in deep scopes
Avoiding footguns comes with experience — often, the footguns are perfectly legal code that can be compiled. Some languages avoid certain footguns (sometimes to introduce other ones). For example, garbage-collected languages remove one class of memory management footguns (at the expense of a GC).
Language-level footguns are probably the biggest class of footguns — e.g., default arguments are mutable in Python, useEffect without dependencies in React, not closing connections in a defer block in Go or the Drop trait in Rust.
Linters can sometimes catch footgun constructions and surface them as warnings. But the most effective way is just learning them.