From a97fad1976e5ef2909f80bf9de0e37fd95245b68 Mon Sep 17 00:00:00 2001 From: Graham Neubig Date: Fri, 6 Feb 2026 06:51:01 -0800 Subject: [PATCH] fix: Add PostHog error tracking for V1 AgentErrorEvent and ConversationErrorEvent (#12543) Co-authored-by: openhands --- .../conversation-websocket-context.tsx | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/frontend/src/contexts/conversation-websocket-context.tsx b/frontend/src/contexts/conversation-websocket-context.tsx index 74d6d8af95..ca858b6b47 100644 --- a/frontend/src/contexts/conversation-websocket-context.tsx +++ b/frontend/src/contexts/conversation-websocket-context.tsx @@ -8,6 +8,7 @@ import React, { useRef, } from "react"; import { useQueryClient } from "@tanstack/react-query"; +import { usePostHog } from "posthog-js/react"; import { useWebSocket, WebSocketHookOptions } from "#/hooks/use-websocket"; import { useEventStore } from "#/stores/use-event-store"; import { useErrorMessageStore } from "#/stores/error-message-store"; @@ -40,7 +41,7 @@ import type { } from "#/api/conversation-service/v1-conversation-service.types"; import EventService from "#/api/event-service/event-service.api"; import { useConversationStore } from "#/stores/conversation-store"; -import { isBudgetOrCreditError } from "#/utils/error-handler"; +import { isBudgetOrCreditError, trackError } from "#/utils/error-handler"; import { useTracking } from "#/hooks/use-tracking"; import { useReadConversationFile } from "#/hooks/mutation/use-read-conversation-file"; import useMetricsStore from "#/stores/metrics-store"; @@ -92,6 +93,7 @@ export function ConversationWebSocketProvider({ const hasConnectedRefMain = React.useRef(false); const hasConnectedRefPlanning = React.useRef(false); + const posthog = usePostHog(); const queryClient = useQueryClient(); const { addEvent } = useEventStore(); const { setErrorMessage, removeErrorMessage } = useErrorMessageStore(); @@ -347,6 +349,15 @@ export function ConversationWebSocketProvider({ // Handle ConversationErrorEvent specifically - show error banner // AgentErrorEvent errors are displayed inline in the chat, not as banners if (isConversationErrorEvent(event)) { + trackError({ + message: event.detail, + source: "conversation", + metadata: { + eventId: event.id, + errorCode: event.code, + }, + posthog, + }); setErrorMessage(event.detail); } else { // Clear error message on any non-ConversationErrorEvent @@ -355,6 +366,16 @@ export function ConversationWebSocketProvider({ // Track credit limit reached if AgentErrorEvent has budget-related error if (isAgentErrorEvent(event)) { + trackError({ + message: event.error, + source: "agent", + metadata: { + eventId: event.id, + toolName: event.tool_name, + toolCallId: event.tool_call_id, + }, + posthog, + }); // Use friendly i18n message for budget/credit errors instead of raw error if (isBudgetOrCreditError(event.error)) { setErrorMessage(I18nKey.STATUS$ERROR_LLM_OUT_OF_CREDITS); @@ -446,6 +467,7 @@ export function ConversationWebSocketProvider({ appendOutput, updateMetricsFromStats, trackCreditLimitReached, + posthog, ], ); @@ -478,6 +500,16 @@ export function ConversationWebSocketProvider({ // Handle AgentErrorEvent specifically if (isAgentErrorEvent(event)) { + trackError({ + message: event.error, + source: "planning_agent", + metadata: { + eventId: event.id, + toolName: event.tool_name, + toolCallId: event.tool_call_id, + }, + posthog, + }); // Use friendly i18n message for budget/credit errors instead of raw error if (isBudgetOrCreditError(event.error)) { setErrorMessage(I18nKey.STATUS$ERROR_LLM_OUT_OF_CREDITS); @@ -586,6 +618,7 @@ export function ConversationWebSocketProvider({ readConversationFile, setPlanContent, updateMetricsFromStats, + posthog, ], );