{"record":{"id":"8345e11eef2fdb8c","repo":"siyuan-note/siyuan","slug":"agent-context-cannot-be-compacted-enough-current","errorCode":null,"errorMessage":"agent context cannot be compacted enough: current user turn not found","messagePattern":"agent context cannot be compacted enough: current user turn not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/agent/agent.go","lineNumber":788,"sourceCode":"\t\t\testimatedMessages, _ := projectImageMessages(messages)\n\t\t\tif !force && estimateProtocolRequestTokens(model, protocol, estimatedMessages, checkpointMsgs,\n\t\t\t\tcompaction, requestTools) <= inputBudget {\n\t\t\t\treturn false, nil\n\t\t\t}\n\n\t\t\tcoveredEntryCount := 0\n\t\t\tpreviousSummary := \"\"\n\t\t\tif compaction != nil {\n\t\t\t\tcoveredEntryCount = compaction.CoveredEntryCount\n\t\t\t\tpreviousSummary = compaction.Summary\n\t\t\t}\n\t\t\tcandidates := compactionCandidateEntryCounts(sessionEntries, coveredEntryCount, userEntryID)\n\t\t\tif len(candidates) == 0 {\n\t\t\t\treturn false, fmt.Errorf(\"%w: the current turn is too large\", errContextCannotBeCompacted)\n\t\t\t}\n\t\t\ttail, ok := currentTurnTail(checkpointMsgs, userEntryID, userMessage)\n\t\t\tif !ok {\n\t\t\t\treturn false, fmt.Errorf(\"%w: current user turn not found\", errContextCannotBeCompacted)\n\t\t\t}\n\n\t\t\tnativeResponsesCompaction := util.IsOpenAIResponsesProtocol(protocol) &&\n\t\t\t\tutil.SupportsOpenAIResponsesCompaction(ctx)\n\t\t\t// 原生 compact 无法限制输出长度，覆盖所有已完成轮次，避免 opaque window 返回后仍超出预算。\n\t\t\tselectedCandidateIndex := len(candidates) - 1\n\t\t\tif !nativeResponsesCompaction {\n\t\t\t\tselectedCandidateIndex = sort.Search(len(candidates), func(i int) bool {\n\t\t\t\t\tcandidate := candidates[i]\n\t\t\t\t\tcandidateCheckpointMsgs := checkpointMessagesAfterCompaction(sessionEntries, candidate, tail)\n\t\t\t\t\tcandidateMessages := checkpointMessagesToOpenAIWithSummary(\n\t\t\t\t\t\tcandidateCheckpointMsgs, language, capabilities, nil)\n\t\t\t\t\tcandidateMessages, _ = projectImageMessages(candidateMessages)\n\t\t\t\t\tbaseTokens := estimateProtocolRequestTokens(model, protocol, candidateMessages,\n\t\t\t\t\t\tcandidateCheckpointMsgs, nil, requestTools)\n\t\t\t\t\treturn compactionSummaryMinTokens <= inputBudget-baseTokens-compactionSummaryOverhead\n\t\t\t\t})\n\t\t\t}","sourceCodeStart":770,"sourceCodeEnd":806,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/agent/agent.go#L770-L806","documentation":"currentTurnTail(checkpointMsgs, userEntryID, userMessage) fails to locate the messages belonging to the current user turn in the checkpoint message list, so compactContext returns errContextCannotBeCompacted with \"current user turn not found\". The runtime expects the pending user entry to correspond to messages at the tail of the checkpoint history; an inconsistency means the compaction tail cannot be reconstructed.","triggerScenarios":"userEntryID does not match any entry in checkpointMsgs — e.g. the session entry list and the checkpoint message list got out of sync, the user entry was not yet appended, or session/history files were edited or corrupted.","commonSituations":"Manually editing or restoring session files; a bug or interrupted write leaving checkpoint messages inconsistent with session entries; passing an already-consumed or wrong userEntryID into the compaction path.","solutions":["Verify the user entry was recorded before compaction runs (entry ordering/id consistency between session entries and checkpointMsgs)","Restore the session from a consistent backup or start a new session if the files are corrupted","Do not hand-edit session history files","If reproducible, debug currentTurnTail inputs: confirm userEntryID and userMessage match the latest checkpoint messages"],"exampleFix":"// before\ncompact(entries, staleUserEntryID, msg) // id from a previous send attempt\n// after\nentry := session.AppendUserEntry(msg)\ncompact(entries, entry.ID, msg) // use the id of the entry actually appended","handlingStrategy":"validation","validationCode":"found := false\nfor _, m := range checkpointMsgs {\n    if m.SessionEntryID == userEntryID {\n        found = true\n        break\n    }\n}\nif !found {\n    return fmt.Errorf(\"userEntryID %s has no matching checkpoint message; refusing to compact\", userEntryID)\n}","typeGuard":null,"tryCatchPattern":"if err := agent.Send(ctx, msg); errors.Is(err, errContextCannotBeCompacted) &&\n    strings.Contains(err.Error(), \"current user turn not found\") {\n    // session state is inconsistent; restore from backup or start a new session\n}","preventionTips":["Never hand-edit or partially restore session history files","Always use the entry ID returned by the send/append call, not a cached one","Ensure the user entry is durably recorded before compaction can trigger","Treat 'session file not found' recovery as full restore, not partial copy"],"tags":["agent","compaction","session-state","inconsistency"],"backgroundTag":"internal-invariant-violation","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}