Skip to content

fix: persist previousRunId across page reloads for v1 threads #2288

Merged
MichaelMilstead merged 5 commits intomainfrom
milst/send-after-threadload
Feb 7, 2026
Merged

fix: persist previousRunId across page reloads for v1 threads #2288
MichaelMilstead merged 5 commits intomainfrom
milst/send-after-threadload

Conversation

@MichaelMilstead
Copy link
Copy Markdown
Contributor

@MichaelMilstead MichaelMilstead commented Feb 7, 2026

  • Store lastCompletedRunId in ThreadState when a run finishes (RUN_FINISHED event) and when thread metadata is fetched from the API
  • Fetch thread metadata (client.threads.retrieve()) in ThreadSyncManager alongside messages, storing lastCompletedRunId for reloaded threads
  • Fall back to lastCompletedRunId in useTamboV1SendMessage when streaming.runId is absent (post-reload scenario)

Problem: After a page reload, switching to an existing thread and sending a message failed with BadRequestError: 400 previousRunId is required. The streaming.runId was only set during active streaming and lost on reload. The server requires
previousRunId when a thread already has messages/runs.

fixes: TAM-1152

@charliecreates charliecreates Bot requested a review from CharlieHelps February 7, 2026 08:30
@github-actions github-actions Bot added area: react-sdk Changes to the React SDK status: in progress Work is currently being done contributor: tambo-team Created by a Tambo team member labels Feb 7, 2026
Copy link
Copy Markdown
Contributor

@charliecreates charliecreates Bot left a comment

Choose a reason for hiding this comment

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

The fix is directionally correct, but there are a couple of robustness and maintainability concerns: handleRunFinished ignores RunFinishedEvent.runId, which can drop lastCompletedRunId in edge cases, and ThreadSyncManager’s sync gating can cause repeated metadata fetches/dispatches when message syncing doesn’t complete. Also, overloading LOAD_THREAD_MESSAGES to carry metadata increases coupling and regression risk; a dedicated action would be clearer.

Additional notes (2)
  • Maintainability | react-sdk/src/v1/utils/event-accumulator.ts:673-680
    handleRunFinished persists lastCompletedRunId from threadState.streaming.runId and ignores the RunFinishedEvent payload entirely. If there are scenarios where streaming state loses runId (or never had it) but the event contains it, this misses a reliable source of truth.

Given the goal is robustness across edge cases, it would be safer to incorporate the event’s runId when present rather than relying solely on streaming state.

  • Maintainability | react-sdk/src/v1/hooks/use-tambo-v1-send-message.test.tsx:1046-1125
    This new test sets up stateWithLastRun with lastCompletedRunId: "run_1" and asserts it’s used as previousRunId. That’s good, but it doesn’t cover the crucial post-reload path this PR claims to fix: metadata fetch populates lastCompletedRunId and then useTamboV1SendMessage uses it.

Right now you only validate the hook’s fallback behavior, not the end-to-end integration between ThreadSyncManager -> reducer -> hook.

Summary of changes

What changed

This PR fixes post-reload message sending for v1 threads by persisting and rehydrating the run identifier required by the server as previousRunId.

Key updates

  • Persist last run in stream state:
    • Added lastCompletedRunId?: string to ThreadState.
    • RUN_FINISHED now stores threadState.streaming.runId into lastCompletedRunId (with fallback to existing).
  • Rehydrate after reload:
    • ThreadSyncManager now fetches both:
      • client.threads.messages.list() (messages)
      • client.threads.retrieve() (metadata)
    • Metadata load dispatches LOAD_THREAD_MESSAGES with lastCompletedRunId to update state without blocking message sync.
  • Use persisted run ID on send:
    • useTamboV1SendMessage now sets previousRunId from threadState.streaming.runId ?? threadState.lastCompletedRunId.
  • Tests updated/added:
    • New hook test asserts lastCompletedRunId is used when streaming.runId is absent.
    • Reducer tests + snapshot updated to cover lastCompletedRunId behavior.

Comment thread react-sdk/src/v1/providers/tambo-v1-stream-context.tsx Outdated
@charliecreates charliecreates Bot removed the request for review from CharlieHelps February 7, 2026 08:33
@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 7, 2026

Codecov Report

❌ Patch coverage is 80.00000% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...t-sdk/src/v1/providers/tambo-v1-stream-context.tsx 72.72% 3 Missing ⚠️
react-sdk/src/v1/utils/event-accumulator.ts 87.50% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 7, 2026

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

Project Deployment Actions Updated (UTC)
cloud Error Error Feb 7, 2026 8:21pm
showcase Ready Ready Preview, Comment Feb 7, 2026 8:21pm
tambo-docs Ready Ready Preview, Comment Feb 7, 2026 8:21pm

Copy link
Copy Markdown
Member

@alecf alecf left a comment

Choose a reason for hiding this comment

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

one minor suggested change - I think this will be a little more reliable/current

I do worry a little about accidentally resetting the latestRunId if this request comes back late or something, but I don't have another better approach right now

Comment thread react-sdk/src/v1/providers/tambo-v1-stream-context.tsx Outdated
@MichaelMilstead MichaelMilstead merged commit 10d1dd0 into main Feb 7, 2026
28 of 29 checks passed
@MichaelMilstead MichaelMilstead deleted the milst/send-after-threadload branch February 7, 2026 20:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: react-sdk Changes to the React SDK contributor: tambo-team Created by a Tambo team member status: in progress Work is currently being done

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants