suiss/ui
  • Docs
  • Components
  • Patterns
  • Interactions
  • Charts
  • Blocks
  • AI
GitHubCreate
DocsComponentsPatternsInteractionsChartsBlocksAICreate
AI21
  • Overview
Conversation
  • Chat
  • Message
  • Prompt Input
  • Suggestion
  • Model Selector
  • Context
  • Checkpoint
  • Inline Citation
Agent steps
  • Chain of Thought
  • Reasoning
  • Tool
  • Confirmation
  • Task
  • Plan
  • Queue
  • Subagent
  • Sources
Output
  • Terminal
  • Stack Trace
  • Test Results
  • File Tree

suiss/ui · AI

Stack Trace

A failed tool call with its stack frames, linking your own frames and folding the framework ones.

import { FileCodeIcon, StackIcon, TerminalIcon } from "@phosphor-icons/react"
import { Bubble, BubbleContent } from "@/components/ui/bubble"
import { CodeBlock, CodeBlockContent } from "@/components/ui/code-block"
import { Message, MessageContent } from "@/components/ui/message"
import {
  Trace,
  TraceCollapsible,
  TraceCollapsibleContent,
  TraceCollapsibleTrigger,
  TraceIcon,
  TraceLine,
  TraceTitle,
} from "@/components/ui/trace"

const FRAME = /^at (.+) \((.+):(\d+):(\d+)\)$/

Stack Trace is a row for a tool call that failed. The error is the title, such as "Failed: TypeError". Open it for the stack frames, which can link to the file and line.

The frames are a TraceCollapsible with a nested Trace. For a failure inside a test run, use Test Results.

Installation

Stack Trace is built with the Trace and Code Block components.

$ pnpm dlx shadcn@latest add @esuiss/trace @esuiss/code-block

Works in any project with a components.json. See Installation for the one-line registry setup. Or use the suiss/ui CLI:

$ pnpm dlx @esuiss/ui@latest add trace code-block

Usage

import {
  Trace,
  TraceCollapsible,
  TraceCollapsibleContent,
  TraceCollapsibleTrigger,
  TraceIcon,
  TraceLine,
  TraceTitle,
} from "@/components/ui/trace"
const [error, ...frames] = stack.split("\n").map((line) => line.trim())

<Trace>
  <TraceCollapsible>
    <TraceCollapsibleTrigger>
      <TraceLine status="error">
        <TraceIcon>
          <CircleXIcon />
        </TraceIcon>
        <TraceTitle>Failed: {error}</TraceTitle>
      </TraceLine>
    </TraceCollapsibleTrigger>
    <TraceCollapsibleContent>
      <div className="flex flex-col gap-2 rounded-md bg-muted p-3 font-mono text-xs">
        <p className="text-destructive">{error}</p>
        <ol>
          {frames.map((frame) => (
            <li
              key={frame}
              className={frame.includes("node_modules") ? undefined : "text-foreground"}
            >
              {frame}
            </li>
          ))}
        </ol>
      </div>
    </TraceCollapsibleContent>
  </TraceCollapsible>
</Trace>

The title truncates, so repeat the full error at the top of the content. Frames from node_modules stay muted, so your own frames stand out.

Examples

Frame links

Turns your own frames into links that open the file at the line, and folds the framework frames into a collapsible row of their own, so the frames you can fix come first.

import { FileCodeIcon, StackIcon, XCircleIcon } from "@phosphor-icons/react"
import {
  Trace,
  TraceCollapsible,
  TraceCollapsibleContent,
  TraceCollapsibleTrigger,
  TraceIcon,
  TraceLine,
  TraceTitle,
} from "@/components/ui/trace"

const FRAME = /^at (.+) \((.+):(\d+):(\d+)\)$/

const STACK = `TypeError: Cannot read properties of undefined (reading 'total')
    at formatInvoice (app/lib/billing.ts:42:31)
    at InvoiceRow (app/components/invoice-row.tsx:18:12)

AI SDK

When a tool throws, its part is output-error. By default errorText is only the error message, with no frames. Return error.stack from onError in toUIMessageStreamResponse to send them.

app/api/chat/route.ts
return result.toUIMessageStreamResponse({
  onError: (error) =>
    error instanceof Error ? (error.stack ?? error.message) : String(error),
})

A stack shows file paths from your server, so only send it in development.

if (part.state === "output-error") {
  const [error, ...frames] = part.errorText
    .split("\n")
    .map((line) => line.trim())

  return <TraceCollapsible>…</TraceCollapsible>
}

Map the other tool states as in Tool.

API Reference

See Trace and Code Block.

import { WarningCircleIcon } from "phosphor-react-native"
import { View } from "react-native"
import { Bubble, BubbleContent } from "@/components/ui/bubble"
import { CodeBlock, CodeBlockContent } from "@/components/ui/code-block"
import { Icon } from "@/components/ui/icon"
import { Message, MessageContent } from "@/components/ui/message"
import { Text } from "@/components/ui/text"
import { TraceCollapsible, TraceCollapsibleContent, TraceCollapsibleTrigger, TraceIcon, TraceLine, TraceTitle } from "@/components/ui/trace"

export function AiStackTraceExample() {
  return (
    <View className="w-full gap-4">
      <Message align="end">
        <MessageContent>
          <Bubble variant="muted">
            <BubbleContent>Reset the database and seed it.</BubbleContent>
import EsuissUI
import PhosphorSwift
import SwiftUI

struct StackTraceExample: View {
  var body: some View {
    VStack(alignment: .leading, spacing: 16) {
      Message(align: .end) {
        MessageContent {
          Bubble(variant: .muted, align: .end) { BubbleContent("Reset the database and seed it.") }
        }
      }
      TraceCollapsible(initiallyExpanded: true) {
        TraceCollapsibleTrigger {
          TraceLine(status: .error) {
            TraceIcon { Ph.warningCircle.regular }
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.adamglin.PhosphorIcons
import com.adamglin.phosphoricons.Regular
import com.adamglin.phosphoricons.regular.WarningCircle
import com.esuiss.ui.components.Bubble
import com.esuiss.ui.components.BubbleContent
import com.esuiss.ui.components.BubbleVariant
import com.esuiss.ui.components.CodeBlock
import com.esuiss.ui.components.CodeBlockContent
import com.esuiss.ui.components.CodeBlockSize
import com.esuiss.ui.components.CodeBlockVariant

Stack Trace on mobile is built from the same parts as on the web: Trace, Code Block, Message, Bubble. The example above is a static demo; connect it to your agent by rendering the same parts from your messages.

Installation

$ pnpm dlx @esuiss/ui@latest add trace code-block message bubble
$ pnpm dlx @esuiss/ui@latest add trace code-block message bubble --platform swift
$ pnpm dlx @esuiss/ui@latest add trace code-block message bubble --platform kotlin

API Reference

See Trace, Code Block, Message, Bubble.

NextTest ResultsPreviousTerminal

On this page

  1. 01Installation
  2. 02Usage
  3. 03Examples
    • Frame links
  4. 04AI SDK
  5. 05API Reference
  6. 06Installation
  7. 07API Reference