Negative random adjustments become zero
In 917D a random adjustment of -1 to -10 is added to a fight value. The code uses the carry flag to detect overflow, but adding a negative (two's complement) number to a value larger than its size always sets the carry, so the routine wrongly concludes that the result has overflowed and returns 0. About 4% of adjustments are negative, so about 4% of attack or defence values collapse to zero. A zeroed defence makes the next blow almost certainly fatal, which explains many of the game's sudden deaths.
Missing wound message
The wound message table at 9190 has no valid entry for a margin of exactly 16. The two bytes read instead are code at 91B0, giving a message address of $2ADD in the ROM, so the game prints garbage.
Wound damage computed with RRCA
The routine at 90DB halves the margin with RRCA instead of SRL. RRCA feeds the bit that falls off the bottom back in at the top, so for many margins the 'halved' value is over 128 and the reduction is either skipped or enormous. For Thorin, margins 3, 7, 11 and 15 do no damage at all, while margins 1, 5, 9 and 13 cut his defence from 120 to about 53 in one blow.
PRINT without a printer jumps into the middle of an instruction
In 805D, if no ZX Printer is attached, a relative jump lands on $8069, the second byte of LD ($B5E3),A. The processor executes the bytes $E3 and $B5 as EX (SP),HL and OR L. In my emulator tests nothing visibly went wrong afterwards, but it is clearly not what was intended; the jump should have gone to 806B.
Thorin never says "get us out of this one, thief!"
In A550 the message 'get us out of this one, thief!' (AFC7) is guarded by a JP Z that follows a JP NC on the same comparison (CP 3). A value of 3 has already been sent elsewhere by the JP NC, so the JP Z is never taken and the line is never said. Presumably a different comparison was intended.
Bard's remembered order is only partly saved
A79F stores Bard's current order in four bytes of his behaviour program (C8D1-$C8D4: instruction, action, target, instrument). SAVE and LOAD copy only the first three of them (8284, 8209), so the instrument of the order (for example the arrow he should shoot with) is not saved; after a LOAD it is whatever it was in the game being played before.
The "another goblin" announcement uses an unset register
When a dead goblin is sent back into play (A36A), the game checks whether Bilbo is in the room it has been moved to, to announce '- another goblin'. But it compares Bilbo's room with register B, which the routine never loads; B still holds a value left over from the attack routine. The new room had just been loaded into A, so B was presumably meant to hold it.
The mended spider web's strength overflows
Each time the spiders mend their web (A950), its strength (byte 5 of its record) is doubled with SLA. It starts at 64, so after one mending it is 128 and after a second it is 0, because the bit shifted out is simply lost. The idea was presumably that the web gets tougher each time.
Breaking something can break the tool for no reason
When something is struck (9257), the instrument's own chance of breaking is worked out with the same faulty overflow test as the fight code (917D): whenever the random adjustment is negative, the total is set to 255 and the instrument breaks. In the emulator, 'break door with bow' against the heavy rock door broke the bow 5 times in 40 tries, although its defence (16 plus at most 21) could never honestly reach the door's 144.
"you are in in a clearing with two stone trolls"
When the trolls turn to stone (A865), the trolls' clearing is given the description 'in a clearing with two stone trolls'. But the room description routine (958E) always prints 'you are' plus the room's preposition ('in') first, so the game says 'you are in in a clearing with two stone trolls'. Seen in the emulator.
Two things shut in different containers are "together"
9DC8 answers 0 for anything shut inside a closed container, without saying which container, and 9D92 then treats two objects that both get the answer 0 as being in the same place, without comparing their rooms. So if Bilbo is shut in the barrel, anything else shut away anywhere in the game counts as within reach. In the emulator, with Bilbo in the closed barrel in the Elvenking's cellar and the sword locked in the closed wooden chest at Bag End, 'take sword' gave 'you take the short strong sword.' With the barrel open, it gave 'I do not see the sword here'.
A loaded game can lose its hidden route
The hidden route closed at the start of a game (970B) is recorded in two places: the blanked-out exit in the room table, which SAVE and LOAD preserve, and the address of the route's entry, which is written into the instruction at A6C3 in Elrond's map routine (A6B8) and is not saved. If a game is loaded in a later session, the room table closes the old route but Elrond's routine points at the route chosen for the new session. When he reads the map he reopens (and names) the wrong exit, and the loaded game's closed route stays closed. (This follows from the code; it was not tried in the emulator.)
Typing DO makes the game run wild
DO is a word in the dictionary, in the same class as ALL, IT, HELP and SAVE, and it comes just before DOOR - so any abbreviation of two letters, such as 'op do', matches DO and not DOOR. But DO is the only word of that class with no entry in the table at 8029, and the 'not in the table' path of 8009 jumps back into the parser without restoring the DE it pushed. Two bytes are left on the stack, so when the parser returns it takes that pushed value as its return address and jumps into the middle of the game's code.

What the player sees is a stray 'what ?', then a fatal blow with nobody named - 'with one well placed blow you cleave his skull' - and then the rivers, the water and other objects 'evaporating' one after another, as the runaway code works through the object table. Nothing has really been attacked: the Z80 is executing whatever it finds.

Traced in the emulator: entering the parser SP is $5EFD, and after DO has been rejected it is $5EFB. 'do', 'op do' and 'attack do' all do it; 'open door', with the noun spelled out to at least three letters, is fine.
Approaching the barrel the wrong way can crash the game
A91B lets the player climb into or jump onto the barrel from an adjoining room, provided the only route there is DOWN - the way the book's escape works. When an exit is found but its direction is anything else, the handler means to print 'you cannot jump onto the barrel from here.' by loading its address into HL and printing it (exactly as the case above it does), but the instruction actually used is a direct JP NZ to that same address, so the Z80 jumps straight into the message's own bytecode and starts executing it as instructions. In one emulator test this sent the program off through a string of unrelated addresses and into an infinite loop inside the routine that saves an unfinished command, freezing the game; the precise garbage path would depend on the exact machine state at the time, but a jump straight into data like this is never going to behave sensibly.

It is reachable in the finished game: standing in the Elvenking's great halls (room 30) or the dark dungeon (room 31) and typing 'climb into barrel' or 'jump onto barrel' while the barrel is in the cellar reaches this path, since both rooms have an exit to the cellar that is not DOWN.