Summary
Running two biorouter run --no-session invocations concurrently causes one of them to abort with a SQLite uniqueness error on the shared messages store:
Error: error returned from database: (code: 2067) UNIQUE constraint failed: messages.session_id, messages.msg_uid
Despite passing --no-session, the concurrent runs appear to share (and race on) a common messages/session database, and one run loses the race. The aborted run produces empty/invalid output (no assistant text, 0 tool calls), so with --output-format json the emitted document is effectively empty.
Environment
- biorouter
1.88.3
- macOS (Apple Silicon)
- Invocation: headless
biorouter run (no TUI), --no-session, --output-format json
Reproduction
Launch two biorouter run --no-session processes at the same time (here with two different providers/models, but the providers are incidental):
# Terminal A / background job 1
biorouter run --no-session --quiet --output-format json \
--provider versa_azure --model gpt-5.5-2026-04-24 --max-turns 50 \
-t "…prompt A…" > a.json 2> a.log &
# Terminal B / background job 2 (started concurrently)
biorouter run --no-session --quiet --output-format json \
--provider versa_bedrock --model us.anthropic.claude-opus-4-8 --max-turns 50 \
-t "…prompt B…" > b.json 2> b.log &
Observed
- One run completes normally.
- The other aborts early; its
.log (stderr) contains:
Error: error returned from database: (code: 2067) UNIQUE constraint failed: messages.session_id, messages.msg_uid
- The aborted run's JSON output is empty/unparseable; the run reports
success: false with 0 tool calls.
- Running the same two commands sequentially (one after the other) both succeed. The failure only occurs when they overlap in time.
Expected
--no-session runs should not persist to — or contend on — a shared session/messages database, and concurrent headless invocations should be isolated from one another (e.g., per-process/in-memory storage, or unique per-run session ids). At minimum, a lost race on the shared store should be retried or surfaced as a clear, non-fatal condition rather than silently emptying the output.
Impact
This makes it unsafe to run headless biorouter run jobs in parallel (e.g., fanning out a benchmark across models). Users must serialize all biorouter run invocations, even with --no-session. The failure mode is also easy to miss because the run still exits and writes an (empty) output file.
Likely cause (speculation, not a fix)
The (session_id, msg_uid) UNIQUE constraint on a messages table suggests that:
--no-session still writes conversation messages to a shared on-disk DB, and/or
- concurrent runs derive the same
session_id (a default/placeholder rather than a per-run unique id), so their message inserts collide, and/or
msg_uid generation isn't unique/atomic across concurrent processes.
Filing as a bug / enhancement; not attempting a fix here — just documenting the behavior and reproduction.
Summary
Running two
biorouter run --no-sessioninvocations concurrently causes one of them to abort with a SQLite uniqueness error on the shared messages store:Despite passing
--no-session, the concurrent runs appear to share (and race on) a common messages/session database, and one run loses the race. The aborted run produces empty/invalid output (no assistant text,0tool calls), so with--output-format jsonthe emitted document is effectively empty.Environment
1.88.3biorouter run(no TUI),--no-session,--output-format jsonReproduction
Launch two
biorouter run --no-sessionprocesses at the same time (here with two different providers/models, but the providers are incidental):Observed
.log(stderr) contains:Error: error returned from database: (code: 2067) UNIQUE constraint failed: messages.session_id, messages.msg_uidsuccess: falsewith0tool calls.Expected
--no-sessionruns should not persist to — or contend on — a shared session/messages database, and concurrent headless invocations should be isolated from one another (e.g., per-process/in-memory storage, or unique per-run session ids). At minimum, a lost race on the shared store should be retried or surfaced as a clear, non-fatal condition rather than silently emptying the output.Impact
This makes it unsafe to run headless
biorouter runjobs in parallel (e.g., fanning out a benchmark across models). Users must serialize allbiorouter runinvocations, even with--no-session. The failure mode is also easy to miss because the run still exits and writes an (empty) output file.Likely cause (speculation, not a fix)
The
(session_id, msg_uid)UNIQUE constraint on amessagestable suggests that:--no-sessionstill writes conversation messages to a shared on-disk DB, and/orsession_id(a default/placeholder rather than a per-run unique id), so their message inserts collide, and/ormsg_uidgeneration isn't unique/atomic across concurrent processes.Filing as a bug / enhancement; not attempting a fix here — just documenting the behavior and reproduction.