Known errors

Stuck for 20 minutes? Copy the exact error, then look it up here.

For an Ollama error, the server log is the first place to look. macOS: cat ~/.ollama/logs/server.log. Linux: journalctl -u ollama --no-pager --follow --pager-end. Windows: server.log in %LOCALAPPDATA%\Ollama.

Stuck on something an earlier chapter set up? Chapter 2's known errors

Which Python and pip

  1. What you see

    error: externally-managed-environment

    Cause

    The Python on your PATH (Homebrew's, or a Linux system Python) is protected by PEP 668.

    Fix

    Make a venv and run its Python: .venv/bin/python -m pip install httpx. Or uv add httpx. Never --break-system-packages.

    Status

    Seen on our Mac (Homebrew 3.14.6).
  2. What you see

    python3 --version prints Python 3.9.6 on a Mac

    Cause

    Apple's /usr/bin/python3 answered first.

    Fix

    Install the pinned Python (uv python install 3.13) and make the venv from it.

    Status

    Seen on our Mac, which has Xcode. Not verified: Macs with only the Command Line Tools.
  3. What you see

    torch installs as 2.8.0, numpy as 2.0.2, with no error

    Cause

    Python 3.9 ran pip. Newer releases need 3.10 or later.

    Fix

    Use the pinned Python. Print sys.version in cell 1.

    Status

    Seen on our Mac: a full pip install torch numpy on Python 3.9.6 gave torch 2.8.0 and numpy 2.0.2, no error.
  4. What you see

    The lockfile at uv.lock needs to be updated, but --locked was provided. (exit 1)

    Cause

    pyproject.toml changed; uv.lock did not.

    Fix

    uv lock, then uv sync --locked.

    Status

    Seen on our Mac (uv 0.12.24, the pinned version, 2026-10-23).
  5. What you see

    uv sync --frozen finishes, but a new package is missing

    Cause

    --frozen uses the old lock and says nothing.

    Fix

    Use --locked in CI.

    Status

    Seen on our Mac (uv 0.12.24, 2026-10-23).
  6. What you see

    NameError in a notebook cell that worked yesterday

    Cause

    A cell above it never ran in this kernel.

    Fix

    Restart the kernel and run all cells.
  7. What you see

    SyntaxError: f-string: unmatched '['

    Cause

    Python 3.11 or older ran a 3.12-style f-string.

    Fix

    Use the pinned Python.

    Status

    Seen on our Mac (3.9.6).

Syntax and values

  1. What you see

    ZeroDivisionError: float division by zero (Python 3.13), or ZeroDivisionError: division by zero (3.14)

    Cause

    A duration of 0.0 in a division, for example one answer chunk.

    Fix

    Check the window first and give None when it is 0.

    Status

    Seen on our Mac: chapter 1's speed.py, line 50, against a stream with one answer chunk (Python 3.13.12; the 3.14 text in an earlier run).
  2. What you see

    TypeError: can only concatenate str (not "int") to str

    Cause

    'tokens: ' + 5

    Fix

    An f-string: f'tokens: {n}'

    Status

  3. What you see

    KeyError: 'message'

    Cause

    A missing key read with [].

    Fix

    msg.get('message', {})
  4. What you see

    AttributeError: 'NoneType' object has no attribute 'get'

    Cause

    .get('message', {}) met a JSON null, which arrives as None.

    Fix

    (msg.get('message') or {}).get('content')

    Status

    Seen on our Mac.
  5. What you see

    AttributeError: module 'statistics' has no attribute 'median' (3.13 and later add "consider renaming")

    Cause

    A file in your folder, statistics.py, hides the real module.

    Fix

    Rename your file.

    Status

    Seen on our Mac (3.14.6; 3.9.6 shows only the bare error).
  6. What you see

    AttributeError: 'dict' object has no attribute 'model'

    Cause

    Dot access on a dict.

    Fix

    d['model'] or d.get('model')

    Status

    Seen on our Mac.
  7. What you see

    SyntaxWarning: "is" with 'int' literal. Did you mean "=="?

    Cause

    x is 200

    Fix

    x == 200
  8. What you see

    TypeError: object of type 'map' has no len()

    Cause

    map() gives a one-pass iterator.

    Fix

    A list comprehension.

    Status

    Seen on our Mac.
  9. What you see

    UnboundLocalError: cannot access local variable 'x' where it is not associated with a value

    Cause

    An assignment later in the function makes the name local.

    Fix

    global x, or pass the value in.

    Status

  10. What you see

    SyntaxError: invalid syntax on a ?? b

    Cause

    Python has no ??.

    Fix

    b if a is None else a

    Status

    Seen on our Mac (3.13.12).
  11. What you see

    A seed or a timeout of 0 silently becomes the default

    Cause

    x or default replaces every false value, and 0 is false.

    Fix

    default if x is None else x

    Status

    Seen on our Mac (3.13.12).
  12. What you see

    Python prints 22.2, JavaScript prints 22.3, for the same number

    Cause

    Python rounds a tie to even; toFixed rounds it up.

    Fix

    Compare numbers within a tolerance, never the printed text.

    Status

    Seen on our Mac (3.13.12, Node v22.23.2).
  13. What you see

    NaN in a results file breaks JSON.parse

    Cause

    Python's json writes NaN by default.

    Fix

    json.dumps(data, allow_nan=False), or write None.

    Status

    Seen on our Mac.

Shapes

  1. What you see

    TypeError: list indices must be integers or slices, not tuple

    Cause

    [:, -1] on a plain list.

    Fix

    [row[-1] for row in rows], or a tensor.

    Status

    Seen on our Mac.
  2. What you see

    Shape (12, 151936) where you wanted (4, 151936)

    Cause

    logits[-1] picked the last batch row.

    Fix

    logits[:, -1, :]

    Status

    In NumPy's docs.
  3. What you see

    Memory grows at every decode step

    Cause

    You kept views of the whole logits block.

    Fix

    .clone() the slice, or logits_to_keep=1.

    Status

    In Transformers' code. Seen on our Mac in NumPy: a slice needed 56 bytes and kept 280 alive.

Streams and async

  1. What you see

    RuntimeWarning: coroutine '...' was never awaited

    Cause

    You called an async def without await.

    Fix

    await it, or asyncio.create_task(...) and keep the task.

    Status

    Seen on our Mac.
  2. What you see

    SyntaxError: 'await' outside function

    Cause

    Top-level await in a script.

    Fix

    asyncio.run(main())

    Status

    Seen on our Mac.
  3. What you see

    RuntimeError: asyncio.run() cannot be called from a running event loop

    Cause

    asyncio.run() in a notebook.

    Fix

    Top-level await in the notebook.
  4. What you see

    TypeError: object dict can't be used in 'await' expression (Python 3.13), or TypeError: 'dict' object can't be awaited (3.14)

    Cause

    await on a plain function's result, like await chat(...).

    Fix

    await asyncio.to_thread(chat, ...)

    Status

    Seen on our Mac (3.13.12 and 3.14.6, 2026-10-23).
  5. What you see

    TypeError: a coroutine was expected, got {...}

    Cause

    asyncio.create_task(chat(...)): chat() already ran and gave a dict.

    Fix

    await asyncio.to_thread(chat, ...)

    Status

    Seen on our Mac (3.13.12).
  6. What you see

    TimeoutError: timed out (bare, not in a URLError)

    Cause

    One read waited longer than timeout.

    Fix

    A longer timeout. Catch TimeoutError too.

    Status

    Seen on our Mac (3.14.6).
  7. What you see

    httpx.ReadTimeout

    Cause

    httpx's 5-second default on a cold call.

    Fix

    timeout=None, or a long read timeout.

    Status

    In httpx's docs.
  8. What you see

    Executing <Task ...> took 1.006 seconds (debug mode)

    Cause

    A blocking call ran inside the loop.

    Fix

    asyncio.to_thread, or an async HTTP client.

    Status

    Seen on our Mac.
  9. What you see

    UnicodeDecodeError while reading a stream

    Cause

    A chunk was decoded alone and ended inside a character.

    Fix

    Split bytes on b"\n" first, or use an incremental decoder.

    Status

  10. What you see

    json.decoder.JSONDecodeError: Unterminated string ...

    Cause

    splitlines() cut a JSON line at U+0085.

    Fix

    Split bytes on b"\n".

    Status

    Seen on our Mac (a made-up line).
  11. What you see

    A line {"error": "..."} mid-stream, while HTTP said 200

    Cause

    The error came after the headers.

    Fix

    Check every line for error. Your port's measure raises RuntimeError.

    Status

    In Ollama's docs.
  12. What you see

    HTTP 503 server busy, please try again. maximum pending requests exceeded

    Cause

    More than 512 requests in the queue.

    Fix

    Send fewer. Retry at one layer only, a few times at most, after a growing, random wait.

    Status

    In Ollama's code (the two spaces are in the source).
  13. What you see

    Almost no errors, but a high p99

    Cause

    An SDK retried for you. The OpenAI SDK retries 2 times by default.

    Fix

    max_retries=0, and count the errors.

    Status

    In the OpenAI SDK's docs.
  14. What you see

    TypeError: 'async_generator' object is not iterable

    Cause

    A plain for over an async generator.

    Fix

    async for, inside an async def.

    Status

    Seen on our Mac (3.12.13, 3.13.12, 3.14.6).
  15. What you see

    A p95 above your slowest request

    Cause

    statistics.quantiles uses its exclusive method by default.

    Fix

    method="inclusive". With fewer than 100 samples, report the count and the max.

    Status

    Seen on our Mac (1369.0 against 631.0).

Threads and processes

  1. What you see

    RuntimeError: An attempt has been made to start a new process before the current process has finished its bootstrapping phase.

    Cause

    No main guard. Spawn imports your file again in each child.

    Fix

    Put the start code under if __name__ == "__main__":.

    Status

    Seen on our Mac (3.13.12, 3.14.6).
  2. What you see

    The script ends, the shell says 0, but the work never ran

    Cause

    The child raised, and the parent did not check exitcode.

    Fix

    Check p.exitcode, or use ProcessPoolExecutor: it fails loudly.

    Status

    Seen on our Mac (3.13.12: exitcode 1, shell status 0).
  3. What you see

    _pickle.PicklingError: Can't pickle <function <lambda> at 0x...>

    Cause

    A lambda sent to a process pool.

    Fix

    A named function at the top of the file.

    Status

    Seen on our Mac (3.14.6).
  4. What you see

    AttributeError: module '__main__' has no attribute '...', then BrokenProcessPool

    Cause

    The function was defined in a notebook or in python -c.

    Fix

    Put it in a .py file.

    Status

    Seen on our Mac (3.14.6).
  5. What you see

    Workers use an old setting, for example the old model name

    Cause

    Spawn re-runs the top-level code. Changes made inside the guard do not reach the children.

    Fix

    Pass settings as arguments.

    Status

    Seen on our Mac (3.13.12).
  6. What you see

    Random prompts are not repeatable across processes

    Cause

    random.seed() in the parent does not reach the children.

    Fix

    Seed each worker: base_seed + worker_id.

    Status

  7. What you see

    DeprecationWarning: This process (pid=...) is multi-threaded, use of fork() may lead to deadlocks in the child.

    Cause

    fork while threads run. Shown only with -W default or -X dev.

    Fix

    Use spawn.

    Status

  8. What you see

    Worker process <pid> died unexpectedly (signal 11) (GuideLLM, macOS)

    Cause

    fork on macOS.

    Fix

    GUIDELLM__MP_CONTEXT_TYPE=spawn

    Status

    In GuideLLM's docs.

Build it and Break it

  1. What you see

    You used launchctl setenv OLLAMA_NUM_PARALLEL 4, and nothing changed

    Cause

    The app was not restarted.

    Fix

    Quit and reopen the Ollama app. Check the server config line in the server log.

    Status

  2. What you see

    You ran export OLLAMA_NUM_PARALLEL=4 in a terminal, and nothing changed

    Cause

    The Mac app does not read your terminal's settings.

    Fix

    launchctl setenv OLLAMA_NUM_PARALLEL 4, then restart the app.

    Status

    In Ollama's docs.
  3. What you see

    Later chapters behave oddly after Break it

    Cause

    OLLAMA_NUM_PARALLEL is still 4.

    Fix

    Undo it for your system (macOS launchctl unsetenv, Linux sudo systemctl revert ollama.service, Windows: delete the variable), restart Ollama, and check the server config line.

    Status

    Seen in chapter 1.
  4. What you see

    Four slots are set, but requests still run one at a time

    Cause

    Ollama v0.40.x serves MLX models one request at a time.

    Fix

    Use the pinned Ollama v0.35.0.

    Status

    In Ollama's code (v0.40.2). Not verified at run time: our Mac stays on v0.35.0.
  5. What you see

    OSError: [Errno 48] Address already in use from drip_server.py

    Cause

    Another program holds port 18434, often an old simulator.

    Fix

    Stop it with Ctrl+C, or use --port 18435 on the server and the matching --url on the client.

    Status

    Seen on our Mac (Python 3.13.12). Not verified: the Linux and Windows texts.
  6. What you see

    OSError: [Errno 24] Too many open files

    Cause

    Too many sockets in one process. On macOS a new terminal starts with a soft limit of 256 open files per process.

    Fix

    Run ulimit -n 2048 in each terminal first (Break it, part 3), or split the streams over more processes.

    Status

    Seen on our Mac (ulimit -n 256, 512 streams, 3.13.12 and 3.14.6; with 2048 the runs passed, 2026-10-09).
  7. What you see

    ModuleNotFoundError: No module named 'timing'

    Cause

    timing.py, chapter 1's helper, is not in the same folder as the script.

    Fix

    Download timing.py from the same page, into the same folder.

    Status

    Seen on our Mac (3.13.12).
  8. What you see

    ModuleNotFoundError: No module named 'drip_server'

    Cause

    Your port's test streams from the simulator, and drip_server.py is not next to it.

    Fix

    Download drip_server.py from the same page, into the same folder.

    Status

    Seen on our Mac (3.13.12, 2026-10-09).
  9. What you see

    fake_ollama.py is missing. Download it from the same page, into this folder.

    Cause

    run_fake.py starts the fake server from fake_ollama.py in its own folder.

    Fix

    Download fake_ollama.py into the same folder.

    Status

    Our script's text.
  10. What you see

    Cannot reach Ollama at http://127.0.0.1:11434. Is it running? [Errno 61] Connection refused

    Cause

    Ollama is not running. Break it, part 3, needs only the simulator.

    Fix

    Open the Ollama app, or run ollama serve.

    Status

    Seen in chapter 1.
  11. What you see

    A script in WSL 2 cannot reach the Ollama app that runs on Windows

    Cause

    In WSL's default network mode, 127.0.0.1 inside WSL is not Windows.

    Fix

    Run Ollama inside WSL 2, or turn on WSL's mirrored network mode (Windows 11 22H2 or newer).

    Status

    In Microsoft's docs. Not verified on Windows.
  12. What you see

    load_client.py warns that client CPU is above 90%

    Cause

    The client is the bottleneck.

    Fix

    Add --processes.

    Status

    Seen on our Mac (Break it, part 3, 2026-10-09; load_client.py line 289).
  13. What you see

    warning: the simulator ran up to ... ms behind its own schedule.

    Cause

    The simulator could not keep its own pace: too many streams for this machine, or other programs busy. Its lag mixes into yours.

    Fix

    Close other programs, or use a smaller --n (the smaller run in Break it, part 3: --n 256, and --work-us 80 in place of 40).

    Status

    Seen on our Mac (7.4 ms, 256 streams and 4 client processes, 2026-10-09).
  14. What you see

    A test fails with a message that names a gap

    Cause

    That gap is not filled yet, or is filled the JavaScript way.

    Fix

    Read the lesson part the message names, then fix that line.

    Status

    Our tests' text (test_speed_port.py).