OneBug This week's bugs

Real bugs, explained.

Every write-up starts as a playable puzzle: find the bug first, then read why it bites in production and how to fix it for good.

JavaScript all JavaScript bugs

TypeScript

Python all Python bugs

Python lambda in loop returns the same value (late binding) Three handlers built in a loop all format the 503 label instead of 404, 500, 503. Python closures read the loop variable at call time. Here is the fix. Remove items from a list while iterating in Python (fix) Deleting matches inside a Python for loop skips elements - one pending task survives. Here is why the loop skips, and the one-line fix that works. Python class attribute shared between instances (list) A list defined in the class body is created once and shared by every instance - one object's append shows up in all of them. The fix is one line in __init__. Python dict assignment doesn't copy - it aliases the dict config = defaults binds a second name to the same dict, so an update() writes into your defaults. How to spot aliasing and copy a dict properly. Python is vs == on integers: True at 256, False at 1000 is compares identity, not value. CPython caches ints from -5 to 256, so small numbers pass an is-check by luck and bigger ones fail it. Use ==. Python mutable default argument: the list that never resets A default argument like applied=[] is created once, at import time, not per call, so every invocation that skips the argument shares and grows the same list. Python str.strip(".txt") strips characters, not a suffix filename.strip(".txt") strips a set of characters from both ends, not the suffix, so names lose extra letters. Here's the fix with removesuffix.

Go all Go bugs

Go len(string) counts bytes, not the characters you see len("cafe") with an accented e returns 5, not 4, so a four-character limit rejects a valid name. Go strings are UTF-8 bytes. Here is the rune-count fix. Go fatal error: concurrent map writes (and the fix) 500 goroutines wrote one map and Go killed the whole process - and recover() cannot save it. Why concurrent map writes are fatal, and how to fix them. Go: assignment to entry in nil map (why writes panic) Writing to a nil map panics in Go while reading it works fine. Here is why var makes a nil map, not an empty one, and the one-line make fix. Go closures capture variables, not values (1.22 or not) Every closure built in the loop returns the same final value, because they all share one captured variable. Why Go 1.22 didn't fix this shape. Go data race: 500 goroutines, a counter that loses count count++ is a read-modify-write, so unsynchronized goroutines overwrite each other's updates. Real -race output, the fix, and the fix that isn't. Go typed nil: err == nil is false after you returned nil Returning a nil *Error through the error interface makes err != nil true on success. Why Go interfaces carry a type, and the one-word fix. Go range loop doesn't update structs: the value-copy trap A Go range loop over a struct slice silently fails to update fields because it copies each element. Here is why, and the one-line index fix. Go slice bug: nums[:0] silently overwrites your input array Appending to a reslice like nums[:0] shares memory with the caller's array, so filtering silently corrupts the original data. Here's why, and the fix.

Java

C

SQL all SQL bugs