Skip to content

fix(copilot): surface error cause chain in sim-to-go span status#5473

Merged
waleedlatif1 merged 1 commit into
stagingfrom
fix/otel-error-cause-chain
Jul 7, 2026
Merged

fix(copilot): surface error cause chain in sim-to-go span status#5473
waleedlatif1 merged 1 commit into
stagingfrom
fix/otel-error-cause-chain

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • markSpanForError only recorded the top-level exception message on the outbound Sim → Go span, so any fetch() failure showed up as the generic TypeError: fetch failed with no indication of the real cause
  • This bit us diagnosing the Sim Mailer inbox processing failures — every failed task's OTel span and stored error message just said "fetch failed" with no way to tell it was ENOTFOUND on a stale SIM_AGENT_API_URL without manually cross-referencing dashboards
  • Use describeError (already in @sim/utils/errors, previously unused here) to walk the .cause chain and surface it as the span status message plus a new error.code attribute

Type of Change

  • Bug fix (observability gap)

Testing

  • tsc --noEmit and biome check clean
  • Verified the exact failure mode this fixes against a real incident: reproduced a TypeError: fetch failed from a dead DNS target and confirmed describeError correctly extracts the underlying ENOTFOUND from .cause

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

markSpanForError only recorded the top-level exception message, so a
fetch() failure showed up as the generic "TypeError: fetch failed" with
no indication of the real cause (ENOTFOUND, ECONNREFUSED, etc). Use
describeError to walk the cause chain and set it as the span status
message and an error.code attribute.
@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 7, 2026 3:17pm

Request Review

@cursor

cursor Bot commented Jul 7, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Observability-only change to span attributes and status messages; no request handling or auth logic is modified.

Overview
markSpanForError in copilot request OTel now uses describeError so Sim→Go and other copilot spans are easier to triage when failures are wrapped (e.g. generic TypeError: fetch failed).

When a structured code exists on the deepest cause, it is stamped on the span as error.code (TraceAttr.ErrorCode). For non–user-stop errors, the span ERROR status message is the .cause chain joined with <- instead of only the outer Error.message. Explicit user-stop handling and recordException behavior are unchanged.

Reviewed by Cursor Bugbot for commit b95c316. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR improves OTel observability in the Sim→Go span path by replacing the bare top-level error message in span status with the full .cause chain surfaced by describeError, and adds the POSIX error code (e.g. ENOTFOUND) as a new error.code span attribute.

  • markSpanForError now calls describeError: if a cause chain exists it joins all links with ' <- ' as the status message; for single-link or non-Error throws it falls back to the existing asError.message.
  • error.code attribute: extracted from the deepest cause link and stamped unconditionally (paralleling the unconditional recordException call), so dashboards can filter by POSIX/system error codes without opening the full trace.

Confidence Score: 5/5

Safe to merge — the change is a two-call addition inside a single helper function with no new failure paths.

The modification touches only markSpanForError, replacing a single asError.message with the richer output of the already-tested describeError. The fallback to asError.message when no cause chain exists preserves existing behavior for plain errors, and describeError is cycle-safe and depth-bounded, so there is no way for the new code to throw or hang. No data path, auth logic, or schema is affected.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/lib/copilot/request/otel.ts Adds describeError to markSpanForError: surfaces the full .cause chain in span status message and stamps error.code from the deepest cause. Logic is correct and edge cases (no chain, non-Error throws, cycles) are handled by the well-tested describeError utility.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Caller
    participant markSpanForError
    participant describeError
    participant Span

    Caller->>markSpanForError: error (e.g. TypeError: fetch failed)
    markSpanForError->>Span: recordException(asError)
    markSpanForError->>describeError: describeError(error)
    describeError-->>markSpanForError: "{ code: "ENOTFOUND", causeChain: ["TypeError: fetch failed", "Error: connect ENOTFOUND ..."] }"
    alt described.code present
        markSpanForError->>Span: setAttribute("error.code", "ENOTFOUND")
    end
    alt not isExplicitUserStopError
        markSpanForError->>Span: "setStatus(ERROR, "TypeError: fetch failed <- Error: connect ENOTFOUND ...")"
    end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Caller
    participant markSpanForError
    participant describeError
    participant Span

    Caller->>markSpanForError: error (e.g. TypeError: fetch failed)
    markSpanForError->>Span: recordException(asError)
    markSpanForError->>describeError: describeError(error)
    describeError-->>markSpanForError: "{ code: "ENOTFOUND", causeChain: ["TypeError: fetch failed", "Error: connect ENOTFOUND ..."] }"
    alt described.code present
        markSpanForError->>Span: setAttribute("error.code", "ENOTFOUND")
    end
    alt not isExplicitUserStopError
        markSpanForError->>Span: "setStatus(ERROR, "TypeError: fetch failed <- Error: connect ENOTFOUND ...")"
    end
Loading

Reviews (3): Last reviewed commit: "fix(copilot): surface error cause chain ..." | Re-trigger Greptile

Comment thread apps/sim/lib/copilot/request/otel.ts
Comment thread apps/sim/lib/copilot/request/otel.ts
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

1 similar comment
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit b95c316. Configure here.

@waleedlatif1 waleedlatif1 merged commit b70b21a into staging Jul 7, 2026
18 checks passed
@waleedlatif1 waleedlatif1 deleted the fix/otel-error-cause-chain branch July 7, 2026 15:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant