Skip to content

Headless runs hang ~30 min on 'sensitive system operation' permission prompts (protected-path writes), then fail with misleading Error: not connected; prompt text corrupts --output-format json #40

Description

@Broccolito

Summary

In non-interactive/headless mode (biorouter run --quiet --output-format json, no TTY), when a tool call triggers a "sensitive system operation" permission prompt — e.g. the developer/shell builtin writing to a protected path like /dev/null — the run has no way to receive approval and hangs for ~25–30 minutes, then aborts with a misleading error:

Error: not connected

The run produces 0 tool calls, (no text response), Success=False, wasting ~30 min. Worse, the permission prompt text is written to stdout, so with --output-format json the emitted document is not valid JSON (it contains the prompt instead of the transcript).

Environment

  • biorouter 1.88.3, macOS (Apple Silicon)
  • BIOROUTER_MODE: auto ("Fully-Automatic mode")
  • Invocation: biorouter run --name <n> --quiet --output-format json --provider <p> --model <m> --max-turns 50 -t "<prompt>"
  • developer builtin enabled; the model occasionally issues a shell command that redirects to /dev/null.

What the --output-format json file contained (instead of JSON)

🔒 Sensitive system operation in Fully-Automatic mode.
This tool call writes to /dev/null (a protected system directory).
Approve it to continue, or deny it. Ordinary file changes run without a prompt in this mode.

stderr: Error: not connected · Elapsed: 1822 s · Tool calls: 0.

Reproduction

Run headlessly with the developer builtin enabled and a prompt that leads the model to run a shell command redirecting to a protected path (e.g. ... 2>/dev/null or echo x > /dev/null):

biorouter run --quiet --output-format json \
  --provider <p> --model <m> --max-turns 50 \
  -t "<prompt that uses the shell tool and writes to /dev/null>"

Observed in ~5% of a 100-question automated batch (non-deterministic — the same /dev/null write was auto-handled and succeeded in other runs).

Impact

  • Hang / wasted time: ~30 min per occurrence in an automated pipeline before it fails.
  • Silent, DoS-like stall: no output, no progress — indistinguishable from a hang.
  • Corrupted structured output: prompt text on stdout breaks any --output-format json consumer.
  • Misleading error: not connected gives no hint that a permission gate is the cause.

Expected behavior (non-interactive mode)

  1. Fail fast (auto-deny) or honor a configured policy (permission.yaml always_allow/ask_before/never_allow) instead of blocking indefinitely on a prompt that can never be answered when there is no TTY / --quiet is set.
  2. Never write prompt text to stdout when --output-format json is set — keep stdout valid JSON; route prompts to stderr/TTY.
  3. Emit a clear, specific error ("operation requires approval; running non-interactively → denied") instead of Error: not connected.

Possible inconsistency in the gate itself

In "Fully-Automatic mode," arbitrary file writes and shell/code_execution are auto-approved (via permission.yaml always_allow), yet a harmless write to /dev/null is hard-gated as a "sensitive system operation." The gating appears inverted from a safety standpoint — a benign discard sink blocks while genuinely powerful operations pass — and it is the direct cause of the hang. Worth reconsidering which operations are gated and ensuring permission.yaml can actually cover/scope the protected-path gate (right now always_allow does not).

Workaround

Disable the developer (and computercontroller) builtins for headless batch runs, so no shell command can trigger the protected-path gate.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions