Skip to content

[Engine] Docker: a run config key in the file GET /config names is silently discarded by the next launch #4425

Closed

Description

@tevenfeng

Area

[Engine] (speed, kernels, models, the server and API) — the server's run config, rewritten by strata launch.

Desktop app, Terminal or source?

Docker

What happened

On a Docker install I added a documented run-config key to the run config file that GET /config names for the running model:

$ curl -s -H "x-api-key: $KEY" http://127.0.0.1:8080/config
{"file": "gyrom.json", "keys": [ … ], "note": "Saved to the run config; used from the next start of the model."}

I added "tool_call_recovery": true (and "reasoning_close_retry": true) to that file at top level, next to "args", then ran docker restart strata. After the restart both keys were gone from the file, the settings were not in effect, and nothing in docker logs strata mentioned it.

The same file is the one Strata's own Model settings card writes: POST /config ends up in serve/runconfig.py:save(path, cfg), which writes the file the server loaded and says the change is "used from the next start of the model". On Docker that promise cannot hold, because the next start goes through strata launch, which re-derives that file from the installed config before the server reads it:

  • docker/entrypoint.sh ends in strata launch --no-tui --access lan … --preset "$PRESET", plus --save-preset "$PRESET" whenever any setting environment variable is set — the normal compose setup (MODEL_PATH, CONTEXT, KV, …).
  • strata_cli/launch/runner.py:build_config() runs on every launch, not only on --save-preset:
    • base = read_config(base_path) — the installed config from setup (strata-<model>.json, /data/install/ in the Docker layout),
    • cfg = derive_config(base, self.s, …) — "the installed one plus the choices that are not setup's",
    • out = launch_dir() / f"{self.name}.json"; write_private(out, cfg) — it overwrites the private run config (the gyrom.json above), and self.config_path = out makes that overwritten file the one the server runs with.

Net effect: in a Docker install there is no path a user has for a run-config key that GET /config does not expose:

  • the Model settings card cannot set it — serve/runconfig.py:EDITABLE lists 16 keys and neither tool_call_recovery nor reasoning_close_retry is among them;
  • strata profile set accepts only OVERRIDE_KEYS (strata_control/profiles.py: host, port, parallel, batch_groups, max_queue, queue_timeout, offline, …);
  • STRATA_SET / launch --set are documented as engine settings or STRATA_* variables;
  • hand-editing the file named by GET /config is discarded by the next launch as shown above.

This matters in practice because both affected keys are the documented remedy for the "a reply ends inside its thinking / a call written in the thinking, so no tool call is delivered and the agent stops" family: tool_call_recovery (docs/DETAILS.md: "On 1,462 agent turns 98.3% read as intended with it and 92.9% without") and reasoning_close_retry (#1053, #2731). Following that advice on a Docker install is what led me to this report.

Smallest steps or command that reproduce it

  1. Docker install, any model, started through the image's own entry point (docker run … -v strata-data:/data … with at least one setting such as MODEL_PATH or CONTEXT, so the entry point re-saves the preset on every start).
  2. Find the file GET /config names:
    curl -s -H "x-api-key: $KEY" http://127.0.0.1:8080/config | head -c 120
    docker exec strata sh -c 'find /data -name "gyrom.json"'      # the same name; the launch writes it under the state folder's launch/ directory
  3. Add "tool_call_recovery": true at top level (not inside "args"), keep a copy: cp gyrom.json gyrom.json.mine.
  4. docker restart strata, wait for the model to load.
  5. Diff: docker exec strata sh -c 'grep -n tool_call_recovery $(find /data -name "*.json")' → nothing; diff against gyrom.json.mine shows the launch rewrote the file. /data/install/strata-<model>.json (the installed config) is unchanged, which is where the key belongs — see the workaround below.

Expected: either the key stays, or the launch says it dropped something.

Reproduction status

Unconfirmed static analysis (I read code or ran a scanner; I did not see it fail)

The loss of the key was observed on a live Docker install (0.2.7, engine 0.1.52) and matches the code path quoted above line for line, but I did not run the sequence myself end to end. Logs, the file before and after, and any further command output I will add on request.

Strata version

Strata 0.2.7 · engine 0.1.52 — Docker image; /props build_info = Strata 0.1.52, /metrics engine.version = 0.1.52

Graphics card, memory and system

NVIDIA GeForce RTX 5060 Ti 16 GB · 64 GB RAM · Linux host, Docker container (/data volume), context 163840, --kv int8, 2 slots

Model, size and settings

Qwen3.8-Flash-Next-Gyro-M TQ2_0 (single GGUF) · 163840 context · kv int8 · parallel 2 · vision on · thinking on at xhigh

Logs

Nothing is logged when the key is dropped — no [strata] … line, no warning — which is part of the report. docker logs strata for that restart shows only the ordinary launch lines (preset, model, tuning kept, engine start). I can attach them, and the before/after copies of the run config, on request; they contain an API key and paths, so I would redact first.

Suggested directions

  1. build_config() could start from the existing private run config when it is newer than the installed one, or merge its keys, instead of deriving it from scratch from base.
  2. Or report the difference the way the [Engine] Tool-call parser silently returns a malformed <function=...> block as plain assistant content #3441 path does: one [strata] … discarded run config key "tool_call_recovery" line would have made this visible in docker logs.
  3. Or expose tool_call_recovery and reasoning_close_retry in serve/runconfig.py:EDITABLE (both are documented config keys in docs/DETAILS.md), so the Model settings card can set them like api_monitor and reasoning_budget_tokens.

Workaround, if this is by design

Put the key in the installed config instead of the private one: /data/install/strata-<model>.json in the Docker layout. derive_config() starts from that file, so the key is copied into the private config on every launch and survives restarts. Worth a line in docs/DOCKER.md next to STRATA_SET, since "edit strata-<model>.json and restart" (docs/DETAILS.md, Quick start step 4) reads as if the file /config shows is that file.

Related issues

Not a duplicate of #4077 / #4078 (parser behaviour, reasoning and tool-call markup) — this is about the run config being rewritten before the server reads it, and it blocks the remedy those threads recommend. #1503 (fixed in 0.2.7) and #2518 are about the conversation cache, not the config file.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions