- Hard to maintain
- Slow
- Hard to extend (slightly different than maintain, but related)
- Crash-prone (but infrequent enough)
- Corrupts data (but infrequent enough)
- Just wrong enough to be annoying but not wrong enough to be useless
I had colleagues on a project (I really wanted to help them fix it, but was never brought on board) that was truly bad code. There was copy/pasta everywhere. The same function written a half dozen or more times with slight differences (or none, no idea why it was copied in the first place), so bug fixes would partially address an issue but not when all copies weren't fixed. It was massive (hundreds of thousands of lines by this point, maybe over a million now) with mostly new team (original coders were contractors, and original team for us all moved on). The size and quality made it hard to extend in a sane way because there were so many unknowns. It had random concurrency issues which would only crop up reliably when fielded.
The fundamental design was flawed. They had to connect N different protocols (each different but communicating the same kind of information) to each other. Instead of coming up with an intermediate format they did 1-to-1 connections, which meant an explosion in complexity. Instead of N translation units to an internal format and N translation units out, it was N * (N - 1) translation units, every protocol needed a way to translate to every other. The sane way would mean adding a new protocol required 2 new translation units, the insane way required 2 * N (the new protocol to all existing protocols, all existing protocols to the new one).
It shipped, it made millions (in revenue) every year, but it was not good code.
There is a wide span between totally 100% correct and totally 100% incorrect code. Most software sits between the two.
I suspect what the parent means is there are some industries where you can't afford for it to break at all. I.e., you don't need to guarantee correctness.