Skip to content

cron: LiveSessionModelSwitchError treated as transient failure — triggers retry loop and Sonnet budget leak #58377

Description

@rayrage213

Summary

When a cron job's isolated agentTurn run hits a LiveSessionModelSwitchError, the cron engine treats it as a transient failure and immediately re-queues the job. This causes a tight retry loop until the gateway restarts — burning fallback budget on every iteration.

Behavior

  1. Cron job fires (Haiku model, sessionTarget: isolated)
  2. Gateway detects the session has a different model locked (Sonnet) → throws LiveSessionModelSwitchError
  3. Fallback chain treats this as a failure → cycles through OpenRouter → then lands on Sonnet (attempt 3 succeeds)
  4. But: cron engine re-fires the job again immediately on the next timer tick (1-min intervals)
  5. Loop repeats 5–6 times until gateway restart clears the session lock

Root Cause

Two distinct issues:

Issue 1: LiveSessionModelSwitchError is non-transient — should not be retried

The fallback chain classifies LiveSessionModelSwitchError as an unknown/transient failure and cycles through all fallback candidates. It should instead:

  • Recognize this as a non-transient session-state error
  • Skip the fallback chain entirely
  • Either fail fast (return error) or resolve the session lock inline

Issue 2: Isolated sessions inherit session model lock from same-agent persistent sessions

Even with sessionTarget: isolated, if the sessionKey field points to a session that has previously run a different model (e.g. Sonnet), the isolated run inherits that session's model binding. The expected behavior for isolated sessions is a fresh session with no model inheritance.

Reproduction

Observed on: 2026-03-31 (multiple windows: 09:11–09:15 UTC, 12:20–12:27 UTC)

Example log sequence:

live session model switch detected before attempt for 9a09f88c: anthropic/claude-haiku-4-5 -> anthropic/claude-sonnet-4-6
model_fallback_decision: candidate_failed | attempt=1 | reason=unknown | errorPreview="Live session model switch requested: anthropic/claude-sonnet-4-6"
live session model switch detected before attempt for 9a09f88c: openrouter/openrouter/auto -> anthropic/claude-sonnet-4-6
model_fallback_decision: candidate_failed | attempt=2 | reason=unknown
model_fallback_decision: candidate_succeeded | attempt=3 | candidateModel=claude-sonnet-4-6

Repeated every ~60s for 5–6 cycles. Same pattern across multiple runIds targeting the same sessionId.

Impact

  • Haiku cron jobs silently run on Sonnet (model cost ~10–20x higher per job)
  • On each cycle: 3 API attempts (Haiku fail → OpenRouter fail → Sonnet succeed)
  • Budget leak proportional to how long the session lock persists

Expected Behavior

  • LiveSessionModelSwitchError should not enter the fallback chain
  • Isolated sessions should not inherit model locks from their parent sessionKey
  • If a model-switch conflict is detected: fail the run immediately with a clear error, increment consecutiveErrors, and respect normal retry backoff

Version

2026.3.28

Workaround

Ensure cron jobs with Haiku model use agentId values whose associated sessions have not been used interactively with Sonnet. Avoids the lock inheritance. Does not address the fallback chain misclassification.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions