siyuan-note/siyuan · error
invalid agent runtime turn
Error message
invalid agent runtime turn
What it means
beginRuntimeTurn rejects a turn that has no TurnID or whose State is not exactly "running" with 'invalid agent runtime turn'. Only a fully-formed, running turn may become the session's ActiveTurn. This enforces the runtime's turn state machine invariant.
Source
Thrown at kernel/agent/runtime.go:257
runtime.SchemaVersion = 1
runtime.SessionID = sessionID
runtime.Revision++
data, err := gulu.JSON.MarshalIndentJSON(runtime, "", "\t")
if err != nil {
return err
}
return filelock.WriteFile(runtimePath(sessionID), data)
}
func beginRuntimeTurn(sessionID string, turn *agentRuntimeTurn) error {
if sessionID == "" || turn == nil {
return nil
}
if !isValidSessionID(sessionID) {
return fmt.Errorf("invalid session id")
}
if turn.TurnID == "" || turn.State != "running" {
return fmt.Errorf("invalid agent runtime turn")
}
lock := sessionLock(sessionID)
lock.Lock()
defer lock.Unlock()
runtime, err := loadRuntimeLocked(sessionID)
if err != nil {
return err
}
if runtime.ActiveTurn != nil && runtime.ActiveTurn.TurnID != turn.TurnID {
committed, err := isTurnCommittedLocked(sessionID, runtime.ActiveTurn.TurnID)
if err != nil {
return err
}
if !committed {
return fmt.Errorf("agent session has an uncommitted turn")
}
runtime.ActiveTurn = nil
}View on GitHub (pinned to 8641553a1f)
Solutions
- Ensure TurnID is assigned (via the runtime's turn-creation helper) before calling beginRuntimeTurn
- Verify turn.State == "running" prior to the call; transition through the proper state machine instead of passing terminal turns
- If reusing a persisted turn, reload it and check its state; create a new turn for new work
Example fix
// before
turn := &agentRuntimeTurn{State: "pending"}
beginRuntimeTurn(sessionID, turn) // rejected
// after
turn := newRuntimeTurn()
turn.State = "running"
beginRuntimeTurn(sessionID, turn) Defensive patterns
Strategy: validation
Validate before calling
if turn == nil || turn.TurnID == "" || turn.State != "running" { return errors.New("turn must be initialized and running") } Type guard
func isRunnableTurn(t *agentRuntimeTurn) bool { return t != nil && t.TurnID != "" && t.State == "running" } Prevention
- Create turns only via the runtime's turn-construction helpers
- Never pass a committed/terminal turn back into beginRuntimeTurn
- Assert turn state in tests before starting turns
When it happens
Trigger: Passing a turn struct that was never initialized (TurnID == ""), or one whose State is a non-running value such as "pending", "committed", or "failed" into beginRuntimeTurn.
Common situations: Reusing a turn object after it was committed or finalized; constructing agentRuntimeTurn by hand without setting TurnID/State; resuming a persisted turn snapshot whose state is terminal.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- agent session has an uncommitted turn
- agent runtime turn is not finalized
- agent runtime user entry not found
- agent runtime turn changed
- agent session revision conflict
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/89e0c0e8ea399221.
Report an issue: GitHub.