siyuan-note/siyuan · error

agent runtime user entry not found

Error message

agent runtime user entry not found

What it means

beginRuntimeTurn verifies that the session's entry list actually contains a user entry whose ID matches turn.UserEntryID (via findRuntimeUserAnchor). If no such anchor exists, the turn has no user message to attach to, so beginning it would create an orphaned turn; the kernel rejects it.

Solutions

  1. Re-read the session state and use the current user entry ID when constructing the turn
  2. Confirm the turn belongs to this session; cross-session entry IDs will never match
  3. If regeneration removed the entry, recreate the user message first (or use the regenerate/recovery path) and then begin the turn with the new entry ID
Defensive patterns

Strategy: validation

Validate before calling

const session = loadSession(sessionID);
if (!session.entries.some(e => e.id === turn.userEntryID && e.type === "user")) throw new Error(`user entry ${turn.userEntryID} not in session; re-read session state`);

Try / catch

if err := beginRuntimeTurn(sessionID, turn); err != nil {
  if strings.Contains(err.Error(), "user entry not found") {
    // refresh session state, rebuild the turn against the current user entry, retry once
  }
}

Prevention

When it happens

Trigger: Calling beginRuntimeTurn with a turn whose UserEntryID references a user entry that does not exist in session.json — a stale/deleted entry ID, an ID from a different session, or an entry removed by regeneration/rollback.

Common situations: Client caching entry IDs across a session regeneration or history rewrite; passing a turn built against another session's entries; an editing operation that removed the user message the turn was derived from.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/b7409775d88fae7d. Report an issue: GitHub.

Appendix: source

Thrown at kernel/agent/runtime.go:288

		}
		if !committed {
			return fmt.Errorf("agent session has an uncommitted turn")
		}
		runtime.ActiveTurn = nil
	}
	data, err := os.ReadFile(filepath.Join(sessionsDir(), sessionID, "session.json"))
	if err != nil {
		return err
	}
	var session map[string]any
	if err := gulu.JSON.UnmarshalJSON(data, &session); err != nil {
		return err
	}
	if turn.BaseRevision >= 0 && numberToInt64(session["revision"]) != turn.BaseRevision {
		return ErrSessionConflict
	}
	if findRuntimeUserAnchor(session, turn.UserEntryID) < 0 {
		return fmt.Errorf("agent runtime user entry not found")
	}
	runtime.ActiveTurn = turn
	return writeRuntimeLocked(sessionID, runtime)
}

func isTurnCommittedLocked(sessionID, turnID string) (bool, error) {
	data, err := os.ReadFile(filepath.Join(sessionsDir(), sessionID, "session.json"))
	if err != nil {
		return false, err
	}
	var meta sessionMeta
	if err := gulu.JSON.UnmarshalJSON(data, &meta); err != nil {
		return false, err
	}
	return meta.LastCommittedTurnID == turnID, nil
}

func saveRuntimeTurn(sessionID string, turn *agentRuntimeTurn) error {

View on GitHub (pinned to 9f775e8a12)