Skip to content

Conversation

@fkesheh
Copy link
Contributor

@fkesheh fkesheh commented Feb 4, 2026

Summary

  • Add diagnostic timeout that fires 10s before Vercel hard timeout to capture what phase the request is stuck in
  • Add phase tracking throughout request lifecycle (streaming, onFinish steps)
  • Add clearPreemptiveOnly() to keep diagnostic timeout alive during onFinish cleanup
  • Add immediate log flush after preemptive timeout trigger to ensure capture before process termination

Extracted from #208 to keep the summarization PR focused.

Test plan

  • Deploy to staging and trigger a long-running chat request
  • Verify diagnostic logs appear in Axiom when request approaches Vercel timeout
  • Verify phase tracking correctly reflects the current lifecycle stage

Summary by CodeRabbit

  • Bug Fixes

    • Improved error recovery mechanisms in streaming operations.
  • Performance & Stability

    • Enhanced timeout management for more reliable chat functionality.

)

* fix(chat): add diagnostic logging for Vercel timeout investigation

- Add diagnostic timeout that fires 10s before Vercel hard timeout
  to capture what phase the request is stuck in
- Add immediate flush after preemptive timeout trigger log to ensure
  it's captured before process termination
- Add phase tracking throughout request lifecycle:
  - streaming, onFinish_started, onFinish_stopSubscriber,
    onFinish_waiting_title, onFinish_updateChat, onFinish_awaitUsage,
    onFinish_saveMessages
- This helps diagnose why only 48/190 timeouts show preemptive triggers

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(chat): keep diagnostic timeout alive during onFinish cleanup

Add clearPreemptiveOnly() to only clear the preemptive timeout at the
start of onFinish, preserving the diagnostic timeout so it can still
fire if onFinish blocks near Vercel's hard limit.

* fix(chat): apply same diagnostic timeout fix to retry/fallback path

Use clearPreemptiveOnly() in the retry onFinish callback to keep the
diagnostic timeout alive during fallback cleanup as well.

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel
Copy link

vercel bot commented Feb 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hackerai Ready Ready Preview, Comment Feb 4, 2026 6:33pm

Request Review

@coderabbitai
Copy link

coderabbitai bot commented Feb 4, 2026

📝 Walkthrough

Walkthrough

These changes enhance the preemptive timeout system with a diagnostic timeout that logs 10 seconds before the Vercel hard timeout, and add granular phase tracking throughout the stream handling lifecycle. A new clearPreemptiveOnly() method allows selective cleanup of the preemptive portion while preserving diagnostic state during retries and late-stage operations.

Changes

Cohort / File(s) Summary
Diagnostic Timeout Infrastructure
lib/utils/stream-cancellation.ts
Introduces a diagnostic timeout that fires 10 seconds before hard timeout and logs phase/timing information with immediate flush. Adds clearPreemptiveOnly() method to clear only preemptive timeout and setPhase(phase) method for phase tracking. Updates clear() to also clear diagnostic timeout.
Phase Tracking & Selective Cleanup
lib/api/chat-handler.ts
Adds phase markers throughout stream lifecycle (streaming, onFinish_started, onFinish_waiting_title, onFinish_updateChat, onFinish_awaitUsage, onFinish_saveMessages, onFinish_stopSubscriber). Replaces full timeout clears with clearPreemptiveOnly() in retry paths to preserve diagnostic timeout state.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • #209: Modifies chat-handler's abort/usage-resolution path and timeout/logging behavior in parallel with this diagnostic enhancement.
  • #205: Directly related; modifies the same codepaths and implements the same new methods (setPhase and clearPreemptiveOnly).
  • #62: Related; modifies the createPreemptiveTimeout implementation in stream-cancellation.ts.

Poem

🐰 A rabbit hops through phases, marking time with care,
Each timeout logged with wisdom before the hard timeout snare,
Preemptive clears yet diagnostic stays to light the way,
Phase by phase we trace the stream until the final day!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately reflects the main change: adding diagnostic logging for Vercel timeout investigation, which is the core objective of both file modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/diagnostic-timeout-logging

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/api/chat-handler.ts (1)

972-981: ⚠️ Potential issue | 🟡 Minor

Clear diagnostic timeout on the early-return path.
Right now this return can leave the diagnostic timer running, which may emit late logs after a clean completion. Consider clearing after deductAccumulatedUsage() and before returning.

Suggested fix
                 if (
                   isAborted &&
                   !isPreemptiveAbort &&
                   newFileIds.length === 0 &&
                   !hasIncompleteToolCalls &&
                   !hasUsageToRecord
                 ) {
                   await deductAccumulatedUsage();
+                  preemptiveTimeout?.clear();
                   return;
                 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant