@@ -67,7 +67,7 @@ function parseTime(value?: string | number | null): number {
6767}
6868
6969/**
70- * Checks if a span or any of its descendants has an error
70+ * Checks if a span or any of its descendants has an error (any error).
7171 */
7272function hasErrorInTree ( span : TraceSpan ) : boolean {
7373 if ( span . status === 'error' ) return true
@@ -80,6 +80,23 @@ function hasErrorInTree(span: TraceSpan): boolean {
8080 return false
8181}
8282
83+ /**
84+ * Checks if a span or any of its descendants has an unhandled error.
85+ * Spans with errorHandled: true (including containers that propagate it)
86+ * are skipped. Used only for the root workflow span to match the actual
87+ * workflow status.
88+ */
89+ function hasUnhandledErrorInTree ( span : TraceSpan ) : boolean {
90+ if ( span . status === 'error' && ! span . errorHandled ) return true
91+ if ( span . children && span . children . length > 0 ) {
92+ return span . children . some ( ( child ) => hasUnhandledErrorInTree ( child ) )
93+ }
94+ if ( span . toolCalls && span . toolCalls . length > 0 && ! span . errorHandled ) {
95+ return span . toolCalls . some ( ( tc ) => tc . error )
96+ }
97+ return false
98+ }
99+
83100/**
84101 * Normalizes and sorts trace spans recursively.
85102 * Deduplicates children and sorts by start time.
@@ -478,14 +495,13 @@ const TraceSpanNode = memo(function TraceSpanNode({
478495 const duration = span . duration || spanEndTime - spanStartTime
479496
480497 const isDirectError = span . status === 'error'
481- const hasNestedError = hasErrorInTree ( span )
498+ const isRootWorkflow = depth === 0
499+ const isRootWorkflowSpan = isRootWorkflow && span . type ?. toLowerCase ( ) === 'workflow'
500+ const hasNestedError = isRootWorkflowSpan ? hasUnhandledErrorInTree ( span ) : hasErrorInTree ( span )
482501 const showErrorStyle = isDirectError || hasNestedError
483502
484503 const { icon : BlockIcon , bgColor } = getBlockIconAndColor ( span . type , span . name )
485504
486- // Root workflow execution is always expanded and has no toggle
487- const isRootWorkflow = depth === 0
488-
489505 // Build all children including tool calls
490506 const allChildren = useMemo ( ( ) => {
491507 const children : TraceSpan [ ] = [ ]
0 commit comments