Make the shipped example envs ones that can actually start
The krow-2 deploy failed on the ANTHROPIC_API_KEY guard, which is the guard doing its job. Checking what an operator hits *after* fixing it turned up two older faults in the files they are told to copy — both predating the Groq switch, both fatal at boot. HTTP_WRITE_TIMEOUT shipped as 30s in .env.example, .env.docker.example and the compose default, while validateWriteTimeout refuses anything at or under the deep tier's 2m deadline. `cp .env.docker.example .env && docker compose up` could not start. Now 180s. krow-2 never saw this because someone had already overridden it in that environment. .env.docker.example carried no model block at all, so a production stack built from it is refused for a missing MODEL_API_KEY. Added, with the Groq defaults and the reasoning-effort note (most non-reasoning models reject the request rather than ignoring the key). Neither was subtle. Both survived because the examples were prose to every test in this package: the validator and the file documenting it had no mechanical connection, so tightening one silently invalidated the other. That connection is now TestShippedExampleEnvActuallyBoots, which parses each example and runs Load() on it under the APP_ENV the file itself declares — production for the docker one, development for the root one, each internally consistent. Verified by mutation: reverting the timeout, removing the key line, and restoring a claude-* id each fail it with the message an operator would see. Go does not treat these files as test inputs, so an example-only edit can be served a stale pass from the test cache. Noted in the test; use -count=1. Also documented the upgrade path in handover.md, including the one thing startup validation cannot catch: renaming ANTHROPIC_API_KEY to MODEL_API_KEY without replacing the value boots fine and 401s on every run. gofmt clean, go vet clean, 15/15 packages pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJvibeSc1JYXjatankqM1g
This commit is contained in:
@@ -196,6 +196,31 @@ otherwise produce a service that boots cleanly and fails every agent run.
|
||||
|
||||
The default with nothing set is Groq.
|
||||
|
||||
### Upgrading a deployment that ran Claude
|
||||
|
||||
A running stack does not migrate itself, and the first thing it does after this
|
||||
change is refuse to start:
|
||||
|
||||
```
|
||||
ERROR fatal error="ANTHROPIC_API_KEY is set but is no longer read, and
|
||||
MODEL_API_KEY is empty: the Anthropic path was removed..."
|
||||
```
|
||||
|
||||
That is the guard working. Two edits to the deployment's env fix it:
|
||||
|
||||
1. `MODEL_API_KEY=<a Groq key>`
|
||||
2. Delete `ANTHROPIC_API_KEY` from the environment entirely.
|
||||
|
||||
**Renaming the variable without replacing the value is the trap.** An
|
||||
`sk-ant-...` under the name `MODEL_API_KEY` passes every startup check — the
|
||||
process cannot tell one opaque string from another — and then fails every run
|
||||
with `the model credentials were refused` and Groq's own text. Startup
|
||||
validation catches the *shape* of a stale configuration, never a wrong secret.
|
||||
|
||||
`ANTHROPIC_API_KEY` is still passed through in `docker-compose.yml` on purpose:
|
||||
a host that kept exporting it gets the loud failure above instead of a
|
||||
container that boots with no credential and fails one run at a time.
|
||||
|
||||
```bash
|
||||
# Groq (the default — base URL and ids below are what you get unset)
|
||||
MODEL_BASE_URL=https://api.groq.com/openai/v1
|
||||
|
||||
Reference in New Issue
Block a user