Skip to content

fix: catch a refused provider key in Lab 0, and three other first-run fixes - #8

Merged
sijie merged 4 commits into
mainfrom
fix/local-first-run-findings
Oct 7, 2026
Merged

sijie merged 4 commits into
mainfrom
fix/local-first-run-findings

Conversation

@sijie

@sijie sijie commented Oct 7, 2026

Copy link
Copy Markdown
Member

Why

I took the Local course end to end on a new Mac (macOS 26.7 on Apple silicon, Docker Desktop 29.8.2 with Compose 5.5.1, ork 0.6.0, the Python path). Every step and every check matched the pages. Four things got in the way of a first run. This PR fixes them, one commit each.

What changes

1. A key the provider refuses is caught in Lab 0, not in Lab 1

local/engine.sh --check and the doctor both passed with a key Anthropic rejects: the engine check only looked for a key in the gateway's environment. The first sign was Lab 1, where the agent retried its first turn for 183 seconds and then stopped with upstream returned 401 … "API key is invalid."

The engine check now asks the provider. With a refused key, local/engine.sh ends like this after about four seconds, and exits 1:

PASS  the AI Gateway is running
PASS  the gateway has a provider key
FAIL  the model provider accepts that key
      fix: the provider answered 401. export ANTHROPIC_API_KEY=<a key it accepts>, then local/engine.sh
PASS  the gateway allows the MCP host risingwave-mcp
PASS  the MCP server answers at http://risingwave-mcp:8000/mcp on the engine's network

1 check(s) failed.
  • How it asks: the harness lists models (GET /v1/models?limit=1) with the key it was started with, through docker exec … node. The key never leaves the engine, and the request costs nothing.
  • Why not through the gateway: its only Anthropic route is /v1/messages, every call needs a session token, and its image has no HTTP client.
  • Other answers: a provider that cannot be reached, or that answers with another status such as 529, is reported as that and never as a bad key.
  • Pages: the Lab 0 step 2 sample output has the new line; Lab 1 and the troubleshooting page no longer say a refused key first shows in Lab 1.

2. Stopping no longer leaves unnamed volumes behind

docker compose down keeps the unnamed volumes that the Kafka and RustFS images declare, and the next up creates new ones. Each local/down.sh and restart left four more empty volumes, and each local/engine.sh one more: nine after one pass through the course.

local/down.sh now removes the containers with rm --volumes before down, and local/engine.sh removes the engine's stopped containers with --volumes. Named volumes hold the data and are not touched.

3. Docs: what Apple's Python 3.9 does to the install command

On a Mac with no other Python, python3 is 3.9.6. runorca needs 3.10 or newer, so pip install -r requirements.txt stops at No matching distribution found for runorca==0.3.0, which does not mention Python. Both courses and "Before you arrive" now say to check python3 --version first, and both troubleshooting pages list the symptom.

4. Docs: ork without Homebrew

The pages gave only brew install orca-ae/tap/ork. A new Mac has no Homebrew, and installing it takes an administrator password. The pages now also name the release archive.

How it was tested

  • Unit tests: local/tests/run.sh goes from 44 checks to 82. Against main's scripts, 16 of the new ones fail.
  • Every commit on its own: shellcheck, local/tests/run.sh and scripts/check-labs.sh pass at each of the four commits.
  • The CI jobs, locally: local, labs and cli pass, and so does the credential scan. I did not run the python and typescript jobs: nothing under python/ or typescript/ changes.
  • The engine check, on the running stack:
    • a working key passes, and the whole check takes 1.2 seconds;
    • a made-up key fails as shown above;
    • a provider host that does not resolve gives the engine cannot reach ….
  • The volumes, on the running stack: with 11 already left behind by earlier runs, unnamed volumes went 11 → 15 on start, stayed at 15 after a second local/engine.sh, and went back to 11 on local/down.sh. After the restart the doctor passed, the topic still held its 253 events, and flagged_accounts still held its row.

Not covered: the Cloud course (it gets only the Python note), and the CLI and TypeScript paths of the Local course.

For the reviewer

  • The engine check relies on node in the harness image, which is a Node server. If a harness cannot make the request, the line fails with the harness could not ask the provider; it does not blame the key.
  • Unnamed volumes left by earlier runs stay where they are. docker volume prune removes them.
  • "What was run" in labs/local/README.md is unchanged: it records your own run.

🤖 Generated with Claude Code

https://claude.ai/code/session_014Nq3n2MeC9XrC31wYfdjZv

sijie and others added 4 commits October 6, 2026 21:44
`local/engine.sh --check` and the doctor both passed with a key the provider
refuses: the engine check only looked for a key in the gateway's environment.
The first sign was Lab 1, where the agent retried its first turn for three
minutes and then stopped with `upstream returned 401`.

The check now asks the provider. The harness lists models with the key it was
started with, so the key stays in the engine and the request costs nothing. A
refused key now fails Lab 0, step 2, within seconds and with its fix. A
provider that cannot be reached, or that answers with another status, is
reported as that, not as a bad key.

The gateway cannot be asked instead: its only Anthropic route is
`/v1/messages`, every call to it needs a session token, and its image has no
HTTP client.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Nq3n2MeC9XrC31wYfdjZv
`docker compose down` keeps the unnamed volumes that the Kafka and RustFS
images declare, and the next `up` creates new ones. Each `local/down.sh` and
restart left four more empty volumes, and each `local/engine.sh` one more:
nine after one pass through the course.

`local/down.sh` now removes the containers with `rm --volumes` before `down`,
and `local/engine.sh` removes the engine's stopped containers with
`--volumes`. Named volumes hold the data and are not touched: after a stop and
a start, the topic, the view and the table are still there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Nq3n2MeC9XrC31wYfdjZv
On a Mac with no other Python, `python3` is 3.9.6. `runorca` needs 3.10 or
newer, so the lab's `pip install -r requirements.txt` stops at
`No matching distribution found for runorca==0.3.0`, which does not mention
Python. Both courses now say to check `python3 --version` first, and both
troubleshooting pages list the symptom.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Nq3n2MeC9XrC31wYfdjZv
The pages gave only `brew install orca-ae/tap/ork`. A new Mac has no Homebrew,
and installing it takes an administrator password. The release archive needs
neither.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Nq3n2MeC9XrC31wYfdjZv
@sijie
sijie merged commit aef76ed into main Oct 7, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant