Skip to content

fix(sessions): skip parent fork when context too large, surface overflow errors#26912

Closed
markshields-tl wants to merge 1 commit intoopenclaw:mainfrom
markshields-tl:fix/thread-session-context-overflow
Closed

fix(sessions): skip parent fork when context too large, surface overflow errors#26912
markshields-tl wants to merge 1 commit intoopenclaw:mainfrom
markshields-tl:fix/thread-session-context-overflow

Conversation

@markshields-tl
Copy link
Contributor

@markshields-tl markshields-tl commented Feb 25, 2026

Summary

Fixes #26905 — Thread sessions forked from parent DM sessions inherit the full parent context and immediately overflow the model's context window, causing silent message failures on Slack.

Changes

1. Skip fork when parent context exceeds threshold (session.ts)

Added PARENT_FORK_MAX_TOKENS (100,000) check before forkSessionFromParent(). When the parent session's totalTokens exceeds this threshold, the thread session starts fresh instead of inheriting a near-full context that would immediately overflow.

The session is still marked forkedFromParent = true to prevent re-fork attempts on subsequent messages.

2. Surface context overflow errors to users (agent-runner-execution.ts)

After the main run loop, if the result contains an embedded context overflow error and no payload text, return a user-visible error message (⚠️ Context overflow — this conversation is too large...) instead of returning kind: 'success' with an empty result. This prevents silent message swallowing on Slack and other channels.

Testing

  • Added test: skips fork and creates fresh session when parent tokens exceed threshold
  • All 34 existing session tests pass
  • TypeScript compiles clean (tsc --noEmit)

Context

This caused 3+ incidents over 2 days in our Slack integration:

  • Parent DM sessions accumulate tokens over hours of conversation
  • Anthropic Opus 4-6 has a 190k token limit
  • Thread sessions forked from a ~170k parent immediately overflow
  • Errors were returned as embedded payloads with usage: {input: 0, output: 0}
  • No error message was surfaced to Slack — messages silently disappeared

AI Disclosure

This PR was authored with assistance from an AI coding agent (OpenClaw/Claude). All changes were reviewed and tested by the submitter.

Greptile Summary

Prevents silent message failures in Slack threads by implementing two complementary fixes:

  • Session forking skip logic: Added PARENT_FORK_MAX_TOKENS (100,000) threshold in session.ts. When a parent DM session exceeds this token count, thread sessions start fresh instead of inheriting a near-full context that would immediately overflow. The session is still marked as forkedFromParent = true to prevent re-fork attempts on subsequent messages.

  • Error surfacing: Enhanced agent-runner-execution.ts to detect when the run completes with an embedded context overflow error but no payload text, and return a user-visible error message (⚠️ Context overflow...) instead of silently returning success with an empty result.

The 100k threshold is reasonable (about 50% of Claude Opus 4-6's 190k token limit) and provides sufficient headroom. The test coverage comprehensively validates the skip-fork behavior. Implementation follows existing patterns and handles edge cases properly (e.g., totalTokens ?? 0 defaults to safe fork behavior when token count is unknown).

Confidence Score: 5/5

  • This PR is safe to merge with no blocking issues
  • The implementation is well-designed with proper error handling, comprehensive test coverage for the core session forking logic, and sensible threshold values. The changes follow existing patterns in the codebase, handle edge cases appropriately, and directly address the reported issue. All TypeScript types are properly used, and the logic is straightforward and auditable.
  • No files require special attention

Last reviewed commit: e9e61ab

…low errors

Two fixes for openclaw#26905 (thread sessions born dead from bloated parent):

1. **Skip fork when parent exceeds 100k tokens** — forkSessionFromParent()
   now checks parentEntry.totalTokens before copying the parent transcript.
   If over PARENT_FORK_MAX_TOKENS (100k), the thread session starts fresh
   instead of inheriting a context that will immediately overflow.

2. **Surface context overflow to users** — When the agent run completes
   with an embedded context overflow error and no payload text, return a
   user-visible error message instead of silently dropping the response.
   Previously, Slack DM sessions would swallow messages with no feedback.

Includes test for the fork-skip behavior.

Closes openclaw#26905
@bmendonca3
Copy link

@markshields-tl Nice fix for surfacing overflow errors instead of returning empty replies.

One edge case: this branch checks only hasPayloadText (runResult?.payloads?.some((p) => p.text?.trim())). If the run returns a non-text payload (for example media-only payloads) plus an overflow meta error, this would still replace a valid payload with the overflow warning.

Could we gate on "any payload content" (text/media/mediaUrls) instead of text-only, and add a regression test for media-only payloads?

steipete added a commit that referenced this pull request Feb 25, 2026
Lands #26912 from @markshields-tl with configurable session.parentForkMaxTokens and docs/tests/changelog updates.

Co-authored-by: Mark Shields <239231357+markshields-tl@users.noreply.github.com>
@steipete steipete closed this Feb 25, 2026
@steipete
Copy link
Contributor

Landed manually on main. Summary:

  • Rebases/cherry-pick landed from this PR, then follow-up enhancement added:
    • configurable session.parentForkMaxTokens (default 100000, 0 disables)
    • docs + config schema/help/labels updates
    • tests for override + validation
    • changelog entry with contributor credit
  • Also keeps the original functional fix from this PR:
    • skip oversized parent thread forks
    • surface embedded context-overflow empty-result failures to users (instead of silent Slack no-reply)
  • Validation run before landing: pnpm lint && pnpm build && pnpm test.

SHAs:

  • Original PR head: e9e61ab
  • Landed on main: eb73e87f1b0b12a9498c94a93f2bc0118d98178e

Thanks @markshields-tl for the fix and report context.

brianleach pushed a commit to brianleach/openclaw that referenced this pull request Feb 26, 2026
…w#26912)

Lands openclaw#26912 from @markshields-tl with configurable session.parentForkMaxTokens and docs/tests/changelog updates.

Co-authored-by: Mark Shields <239231357+markshields-tl@users.noreply.github.com>
@markshields-tl
Copy link
Contributor Author

markshields-tl commented Feb 26, 2026

Thank you for approving @steipete !

Was pleasantly surprised to see myself listed as a contributor in the latest release.

execute008 pushed a commit to execute008/openclaw that referenced this pull request Feb 27, 2026
…w#26912)

Lands openclaw#26912 from @markshields-tl with configurable session.parentForkMaxTokens and docs/tests/changelog updates.

Co-authored-by: Mark Shields <239231357+markshields-tl@users.noreply.github.com>
r4jiv007 pushed a commit to r4jiv007/openclaw that referenced this pull request Feb 28, 2026
…w#26912)

Lands openclaw#26912 from @markshields-tl with configurable session.parentForkMaxTokens and docs/tests/changelog updates.

Co-authored-by: Mark Shields <239231357+markshields-tl@users.noreply.github.com>
vincentkoc pushed a commit to Sid-Qin/openclaw that referenced this pull request Feb 28, 2026
…w#26912)

Lands openclaw#26912 from @markshields-tl with configurable session.parentForkMaxTokens and docs/tests/changelog updates.

Co-authored-by: Mark Shields <239231357+markshields-tl@users.noreply.github.com>
vincentkoc pushed a commit to rylena/rylen-openclaw that referenced this pull request Feb 28, 2026
…w#26912)

Lands openclaw#26912 from @markshields-tl with configurable session.parentForkMaxTokens and docs/tests/changelog updates.

Co-authored-by: Mark Shields <239231357+markshields-tl@users.noreply.github.com>
steipete added a commit to Sid-Qin/openclaw that referenced this pull request Mar 2, 2026
…w#26912)

Lands openclaw#26912 from @markshields-tl with configurable session.parentForkMaxTokens and docs/tests/changelog updates.

Co-authored-by: Mark Shields <239231357+markshields-tl@users.noreply.github.com>
zooqueen pushed a commit to hanzoai/bot that referenced this pull request Mar 6, 2026
…w#26912)

Lands openclaw#26912 from @markshields-tl with configurable session.parentForkMaxTokens and docs/tests/changelog updates.

Co-authored-by: Mark Shields <239231357+markshields-tl@users.noreply.github.com>
thebenjaminlee pushed a commit to escape-velocity-ventures/openclaw that referenced this pull request Mar 7, 2026
…w#26912)

Lands openclaw#26912 from @markshields-tl with configurable session.parentForkMaxTokens and docs/tests/changelog updates.

Co-authored-by: Mark Shields <239231357+markshields-tl@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Thread sessions inherit overflowed parent context, born dead with silent failure

3 participants