Skip to content

fix: compaction-safeguard causes HTTP 400 error instead of graceful skip when no conversation messages #32759

Description

@zymclaw

Bug Summary

The compaction-safeguard mechanism triggers HTTP 400 status code (no body) errors when it detects sessions with no "real conversation messages to summarize". Instead of gracefully handling this edge case (e.g., skipping compaction silently), it propagates an error to the user-facing API response.

Environment

  • OpenClaw Version: 2026.2.26
  • Model: GLM-5 (unicom provider)
  • Context Window: 200k (default)
  • Channels: Feishu (enabled), iMessage (disabled due to permission issues)

Steps to Reproduce

  1. Have an active session with many tool calls but few/no user text messages
  2. Session accumulates messages where all content is tool_result type (no user or assistant role messages)
  3. Compaction triggers (possibly due to other conditions)
  4. compaction-safeguard detects "no real conversation messages"
  5. Observe HTTP 400 status code (no body) error in user-facing response

Expected Behavior

When compaction-safeguard detects no valid conversation messages to summarize, it should:

  • Silently skip the compaction operation
  • Return a friendly message or continue normal operation
  • Log the event for debugging purposes

Actual Behavior

When compaction-safeguard triggers, it causes:

[compaction-safeguard] Compaction safeguard: cancelling compaction with no real conversation messages to summarize.
[agent/embedded] embedded run agent end: runId=xxx isError=true error=400 status code (no body)

The user receives HTTP 400: status code (no body) error, which is confusing and provides no actionable information.

Evidence

Session Analysis

The affected session file (4e576660-cdce-46e0-a9ff-8f7407b9ab15.jsonl.reset) shows:

  • File size: 171KB (53 lines)
  • Session duration: 2026-03-02 22:00 ~ 2026-03-03 05:42 (~8 hours)
  • Message types: 49 messages, ALL with role: null (tool_result only)
  • No user or assistant messages - only system-generated tool results
$ cat session.jsonl | jq -r 'select(.type == "message") | .role' | sort | uniq -c
  49 null   # All messages have null role = tool_result

Log Pattern

2026-03-03T05:42:33.097Z [compaction-safeguard] Compaction safeguard: cancelling compaction with no real conversation messages to summarize.
2026-03-03T05:42:35.680Z [agent/embedded] embedded run agent end: runId=7477cd1d-d20c-46fc-a6eb-08073e98f8fd isError=true error=400 status code (no body)
2026-03-03T05:42:35.691Z [compaction-safeguard] Compaction safeguard: cancelling compaction with no real conversation messages to summarize.

Occurrences

Over ~8 hours, this pattern occurred 24 times (compaction-safeguard logs on 2026-03-03):

Time Period Count
00:37 - 00:39 6
01:55 3
02:08 - 02:21 9
03:42 6
Total 24 safeguard triggers

Source Code Reference

From pi-embedded-*.js:

log.warn("Compaction safeguard: cancelling compaction with no real conversation messages to summarize.");

The safeguard correctly identifies the condition but the cancellation results in an error response rather than graceful handling.

Root Cause Analysis

Why did the session have no "real conversation messages"?

The session was primarily composed of:

  1. Tool call results (system-generated, role: null)
  2. No explicit user text messages or assistant responses in the conversation history

This can happen when:

  • Heavy tool usage sessions (agent continuously processing without explicit user input)
  • Session state becomes inconsistent after channel errors
  • Messages were already compacted/summarized, leaving only tool results

Why does safeguard trigger error instead of graceful skip?

The compaction-safeguard correctly cancels the compaction operation, but the cancellation propagates as an error up the stack, resulting in HTTP 400 being returned to the user.

Suggested Fix

  1. Graceful degradation: When safeguard triggers, skip compaction and continue normally
  2. Better error message: If an error must be returned, provide actionable context
  3. Return to normal flow: Allow the original request to proceed without compaction
// Suggested handling
if (!hasRealConversationMessages) {
    log.warn("Compaction safeguard: skipping compaction - no real conversation messages");
    // Skip compaction, but continue with the request
    return { skipped: true, reason: "no_conversation_messages" };
}

Workaround

User can run /new to start a fresh session, which clears the problematic session state.

Related Issues

Impact

This affects user experience significantly:

  • Confusing error message with no actionable guidance
  • Disrupts ongoing conversations
  • May happen repeatedly in affected sessions
  • Users may not understand why the error occurs

Additional Context

This issue was discovered during a session that had continuous iMessage permission errors (Messages database access denied), which may have contributed to the unusual session state. However, the core issue (safeguard causing HTTP 400 instead of graceful handling) is independent of the iMessage errors.

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