fix: batch resolve 5 PostHog production errors (chat error handling)#344
fix: batch resolve 5 PostHog production errors (chat error handling)#344
Conversation
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Codex <noreply@openai.com>
…i (PostHog #019d510a) Gemini rejects message history where an assistant function-call turn isn't immediately followed by a function-response turn. The set-based logic in stripOrphanedToolCalls proved a tool-result existed *somewhere* in history but didn't enforce that it sat in the slot Gemini requires, causing 158 exceptions across 58 users in production. Add a belt-and-suspenders adjacency repair pass that walks the surviving messages and drops any unpaired tool-call (or stray tool message). Live approval state is preserved (the runtime appends the approval-response before the next turn). The pass returns a drop count which is logged through console.warn so a regression in upstream persistence is observable in Convex logs. - Add convex/ai/toolCallAdjacency.ts with the repair logic and a drop counter. - Wire it into stripOrphanedToolCalls in convex/ai/contextWindow.ts. - Add 7 regression tests in convex/ai/toolCallAdjacency.test.ts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… #019dea0c, #019d96f1) The /chat welcome page calls api.chat.createThreadWithMessage but didn't route the thrown errors through the existing parseByokError + FailureBanner pattern that ChatInput already uses. Result: rate-limit and BYOK provider errors (Gemini quota, Anthropic credit, prepayment depleted) leaked as uncaught exceptions and showed users a generic 'Could not send your message' instead of an actionable banner. - src/app/(app)/chat/page.tsx: add byokError state; classify errors in both the auto-send useEffect and suggestion-button .catch; render FailureBanner with priority over the generic <p>. - src/app/(app)/chat/WelcomeInput.tsx: same treatment for manually-typed welcome submissions; add console.error so unclassified failures leave a debuggable trail. Mirrors the established pattern in src/features/chat/ChatInput.tsx. No new dependencies, no refactor of unrelated code. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (22)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
|
Caution Review failedFailed to post review comments 📝 WalkthroughWalkthroughThis pull request introduces Garmin workout delivery functionality enabling users to send Roni training plans to Garmin devices, adds adjacency repair for orphaned tool-calls in AI conversations, implements bring-your-own-key error handling in chat, and integrates account deletion support for the new Garmin delivery table. ChangesGarmin Workout Delivery Feature
Account Deletion & User Data Integration
AI Tool-Call Adjacency Repair
Chat Bring-Your-Own-Key Error Handling
Sequence DiagramsequenceDiagram
participant User as User
participant UI as Schedule Day Page
participant Card as GarminWorkoutDeliveryCard
participant Query as Convex Query
participant Action as sendWorkoutPlanToGarmin Action
participant Validate as Validation & Auth
participant RateLimit as Rate Limiter
participant PayloadBuilder as Payload Builder
participant GarminAPI as Garmin Training API
participant DB as Database
User->>UI: View schedule day with workout
UI->>Card: Render card (workoutPlanId, scheduledDate)
Card->>Query: Fetch delivery status & connection
Query-->>Card: Return delivery & connection state
Card-->>UI: Display status (unsent/sent/failed) & button
User->>Card: Click "Send to Garmin"
Card->>Card: Set loading=true
Card->>Action: sendWorkoutPlanToGarmin(workoutPlanId, scheduledDate)
Action->>Validate: Validate date format & user permissions
Validate-->>Action: ✓ Authorized
Action->>RateLimit: Check rate limit (sendGarminWorkout)
RateLimit-->>Action: ✓ Within quota
Action->>DB: startDeliveryAttempt(userId, workoutPlanId, scheduledDate)
DB-->>Action: deliveryId in 'sending' state
Action->>Action: Decrypt Garmin credentials
Action->>Action: Fetch workout plan & movements
Action->>PayloadBuilder: buildGarminStrengthWorkoutPayloadFromPlan(plan)
PayloadBuilder-->>Action: GarminWorkoutPayload
Action->>GarminAPI: createAndScheduleGarminWorkout(credentials, payload, date)
GarminAPI-->>Action: {garminWorkoutId, garminScheduleId}
Action->>DB: markDeliverySent(deliveryId, garminIds)
DB-->>Action: Updated delivery (status='sent')
Action-->>Card: SendGarminWorkoutResult (success)
Card->>Card: Set loading=false
Card->>Query: Refetch delivery status
Query-->>Card: Return sent delivery
Card-->>UI: Display "Sent to Garmin" + timestamp
Card-->>User: ✓ Workout scheduled on Garmin device
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts
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. Comment |
Summary
Batch fix for PostHog production errors. Two independent fixes share this PR because both target the chat error path:
Convex (
stripOrphanedToolCallsadjacency repair) — addresses PostHog #019d510a (158 occurrences, 58 affected users), the highest-impact unresolved issue. Gemini was rejecting our message history with "Please ensure that function call turn comes immediately after a user turn or after a function response turn." The existing strip pass proved a tool-result existed somewhere in history but didn't enforce that it sat in the slot Gemini requires.Next.js (welcome-page BYOK error classification) — addresses a cluster of issues (#019d7fcc 50 occ, #019dea0c 8 occ, #019d96f1 2 occ, etc.) where errors thrown by
api.chat.createThreadWithMessage(rate-limit + BYOK provider failures) leaked as uncaught exceptions on/chatbecause the welcome page didn't route them through the existingparseByokError→FailureBannerpattern thatChatInputalready uses.Fixes
convex/ai/contextWindow.ts,convex/ai/toolCallAdjacency.tsconsole.warnwith drop count for observability.src/app/(app)/chat/page.tsx,src/app/(app)/chat/WelcomeInput.tsxparseByokError; renderFailureBannerinstead of generic string.Test plan
convex/ai/toolCallAdjacency.test.ts— 7 new regression tests covering: text-only follower, fresh-user follower, matched tool-result, mismatched tool-result id, live-approval flow, leading-tool-message, two consecutive tool messages.convex/ai/stripOrphanedToolCalls.test.ts— 12 existing tests still pass (set-based logic unchanged).convex/ai/contextWindow.test.ts— 22 existing tests pass.npx tsc --noEmit— clean.npm run lint— clean.Skipped
PostHog has many active error-tracking issues whose root cause is outside our code; left active in PostHog (operator action only):
window.__firefox__.reader), Chromeruntime.sendMessage,Script error.from cross-origin scripts,n.standardSelectors,ResizeObserver loop completed. Not our code.NetworkError when attempting to fetch resource (chatty-hawk-29.convex.cloud),Failed to fetch,Load failed. Expected churn; not actionable in code.ChunkLoadError, 2 issues): low priority; could be improved with a stale-tab refresh prompt as a follow-up.Deferred — needs human input
None.
Dropped after failed verification
None.
Observability
The new adjacency repair pass emits
console.warnwith a drop count when it triggers. Watch Convex logs for[stripOrphanedToolCalls] adjacency repair dropped N message(s)/part(s)— sustained drops there indicate a regression in upstream message persistence (the bug class this pass defends against).🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Tests
Other