Skip to content

Add trace ID extraction and appending to error messages - #1664

Open
djeebus wants to merge 4 commits into
mainfrom
claude/trace-id-error-messages-cbzqwl
Open

Add trace ID extraction and appending to error messages#1664
djeebus wants to merge 4 commits into
mainfrom
claude/trace-id-error-messages-cbzqwl

Conversation

@djeebus

@djeebus djeebus commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

This change adds trace ID extraction from HTTP response headers and appends them to error messages across the SDK and CLI. When API or envd requests fail, the error message now includes the trace ID (e.g., (trace ID: abc123)) so users can report it to E2B support for correlation with server-side traces.

Usage examples

No behavioral API changes — the trace ID shows up in existing error messages when the failed response carries a trace header.

JS SDK

import { Sandbox } from 'e2b'

try {
  await Sandbox.connect('already-dead-sandbox-id')
} catch (err) {
  console.error(err.message)
  // 404: sandbox not found (trace ID: 105445aa7843bc8bf206b12000100000)
}

Python SDK (sync and async)

from e2b import Sandbox

try:
    Sandbox.connect("already-dead-sandbox-id")
except Exception as e:
    print(e)
    # 404: sandbox not found (trace ID: 105445aa7843bc8bf206b12000100000)

CLI

$ e2b sandbox logs already-dead-sandbox-id
Error while getting sandbox logs: [404] not found: sandbox not found (trace ID: 105445aa7843bc8bf206b12000100000)

Key Changes

  • Trace ID parsing: packages/js-sdk/src/traceId.ts (single implementation, exported as extractTraceId from the e2b package and reused by the CLI) and e2b/trace_id.py (exported as extract_trace_id for JS/Python parity):

    • Extract trace IDs from response headers in priority order: X-Trace-ID (direct), X-Cloud-Trace-Context (GCP edge), X-Amzn-Trace-Id (AWS edge)
    • Normalize AWS trace IDs from Root=1-<8 hex>-<24 hex> to the 32-hex form the server logs as edge_trace_id
  • Error classes carry the trace ID in the constructor and append it to the message: SandboxError(message, stackTrace, traceId) and the other JS classes (uniform 3-arg shape, including AuthenticationError/GitAuthError); SandboxException(message, trace_id) and the other Python exception roots. apiErrorFromCode / api_exception_from_code and the envd error maps thread the trace ID through.

  • Wiring: handleApiError (JS), handle_api_exception (Python), handleEnvdApiError / handle_envd_api_exception / ahandle_envd_api_exception (envd HTTP), and the CLI's handleE2BRequestError read the response headers and pass the extracted ID into the error constructors.

  • Not covered — envd RPC (connect) paths: sandbox.commands / sandbox.files RPC errors do not carry the trace ID, because Python's connectrpc.ConnectError exposes no response metadata, and the JS side is kept symmetric. This is where most in-sandbox failures surface, so the feature currently reaches HTTP API and envd HTTP (file transfer) errors only.

  • Test coverage: header extraction and normalization edge cases, priority ordering, case-insensitivity, missing-header fallbacks, custom errorClass/error_map pass-through, and CLI parsing — in JS, Python (sync + async), and the CLI.

Note on the server side

Verified against production (2026-08-13): no failed api.e2b.dev or sandbox-edge response currently returns any trace header, so this change is inert until the server emits one. The API handlers already compute the trace ID (c.Set("traceID", traceID) in infra) — a one-line c.Header("X-Trace-ID", traceID) there would activate the primary path. The GCP/AWS edge-header branches are speculative (those are request-side conventions); whether to keep them or trim to X-Trace-ID-only once the infra change lands is an open reviewer question for @djeebus.

https://claude.ai/code/session_0147b6bTi2gq4Yvm7VrLrxLD

When a failed API or envd response carries a trace header (X-Trace-ID,
or the GCP X-Cloud-Trace-Context / AWS X-Amzn-Trace-Id edge headers),
the JS SDK, Python SDK (sync and async), and CLI now append
'(trace ID: ...)' to the error message so users can report the ID and
it can be correlated with server-side traces.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0147b6bTi2gq4Yvm7VrLrxLD
@djeebus
djeebus requested a review from mishushakov as a code owner August 12, 2026 00:38
@cla-bot cla-bot Bot added the cla-signed label Aug 12, 2026
@changeset-bot

changeset-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: b7eeae2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
e2b Patch
@e2b/python-sdk Patch
@e2b/cli Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@cursor

cursor Bot commented Aug 12, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Optional constructor parameters and message formatting only; no change to request or auth behavior.

Overview
Failed API, envd, and CLI request errors can now end with (trace ID: ...) when the response has X-Trace-ID, X-Cloud-Trace-Context, or X-Amzn-Trace-Id (AWS values are normalized to 32-hex when possible). New extractTraceId / extract_trace_id helpers are exported; SDK exception constructors take an optional trace ID and the shared handlers pass it through. Envd connect/RPC errors are unchanged. Messages stay the same when no trace header is present.

Reviewed by Cursor Bugbot for commit b7eeae2. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Package Artifacts

Built from 84e7f36. Download artifacts from this workflow run.

JS SDK (e2b@2.39.1-claude-trace-id-error-messages-cbzqwl.0):

npm install ./e2b-2.39.1-claude-trace-id-error-messages-cbzqwl.0.tgz

CLI (@e2b/cli@2.16.2-claude-trace-id-error-messages-cbzqwl.0):

npm install ./e2b-cli-2.16.2-claude-trace-id-error-messages-cbzqwl.0.tgz

Python SDK (e2b==2.39.1+claude.trace.id.error.messages.cbzqwl):

pip install ./e2b-2.39.1+claude.trace.id.error.messages.cbzqwl-py3-none-any.whl

@djeebus
djeebus enabled auto-merge (squash) August 12, 2026 00:39
Comment thread packages/cli/src/utils/errors.ts Outdated
Comment on lines 60 to 79
if (key?.toLowerCase() !== 'root' || !value) {
continue
}

const match = value.match(/^1-([0-9a-f]{8})-([0-9a-f]{24})$/i)
return match ? match[1] + match[2] : value
}
}

return undefined
}

function throwE2BRequestError(
error: E2BResponseError,
errMsg?: string,
traceId?: string
): never {
let message: string
const code = error.code ?? 0
switch (code) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 CLAUDE.md requires 'Create or update tests covering affected codepaths,' but this PR leaves packages/cli/tests/utils/errors.test.ts untouched even though errors.ts gains a new extractTraceId() function and trace-ID appending in throwE2BRequestError/handleE2BRequestError. No case exercises X-Trace-ID, GCP X-Cloud-Trace-Context, or AWS X-Amzn-Trace-Id extraction/normalization for the CLI, unlike the JS SDK (new traceId.test.ts + updated handleApiError.test.ts/handleEnvdApiError.test.ts) and Python SDK (test_trace_id.py), which both got full coverage for the identical logic.

Extended reasoning...

This PR introduces a new, non-trivial codepath in packages/cli/src/utils/errors.ts: extractTraceId() parses three different header formats (a direct X-Trace-ID, the GCP X-Cloud-Trace-Context edge header which requires splitting on /, and the AWS X-Amzn-Trace-Id edge header which requires parsing a Root=1-<8 hex>-<24 hex> field and normalizing it into a 32-hex trace ID), and it wires the extracted value into throwE2BRequestError/handleE2BRequestError so it gets appended to the thrown error message as (trace ID: ...).

None of this is covered by tests in the CLI package. packages/cli/tests/utils/errors.test.ts already exists and already tests handleE2BRequestError for various status codes, but the PR leaves it completely untouched — a grep for trace/Trace across packages/cli/tests returns nothing. There is no test that passes a response/headers-bearing object into handleE2BRequestError, so none of the three extraction branches, the AWS regex normalization, the priority ordering (direct > GCP > AWS), or the final message-appending behavior is exercised at all for the CLI.

This is a direct violation of the repository's own CLAUDE.md instructions, which explicitly state: 'Create or update tests covering affected codepaths and run them using pnpm run test.' The PR's own diff demonstrates the intended standard: the JS SDK got a full new traceId.test.ts (extraction, normalization, priority ordering, edge cases) plus updated handleApiError.test.ts and handleEnvdApiError.test.ts with trace-ID-specific cases, and the Python SDK got a full new test_trace_id.py covering the same logic end to end. The CLI implementation — which, per the related duplication finding, re-implements this parsing logic independently rather than sharing it with the SDK's traceId.ts — is the only one of the three places this feature landed that received zero test coverage.

Concrete proof of the gap: take the AWS-header path, since it's the most failure-prone (regex parsing + normalization). In extractTraceId, if X-Amzn-Trace-Id is Root=1-5759e988-bd862e3fe1be46a994272793;Sampled=1, the code should return 5759e988bd862e3fe1be46a994272793 (the two hex groups joined), and this exact case is verified in both packages/js-sdk/tests/traceId.test.ts and packages/python-sdk/tests/test_trace_id.py. But if the CLI's regex or splitting logic were subtly wrong — e.g. an off-by-one in the hex-group lengths, or the ; split failing to find Root= first — nothing in pnpm run test for the CLI package would catch it, since handleE2BRequestError is only ever invoked in the test suite without a response argument. The same blind spot applies to the GCP-header branch and to the case-insensitivity of headers.get('x-trace-id').

Fix: add test cases to packages/cli/tests/utils/errors.test.ts mirroring the ones already written for the JS SDK — pass a response: { headers: new Headers({...}) } into handleE2BRequestError and assert the thrown E2BRequestError's message ends with (trace ID: ...) for each of: direct X-Trace-ID, GCP X-Cloud-Trace-Context, AWS X-Amzn-Trace-Id (including the raw-fallback case for a malformed Root= value), priority ordering when multiple headers are present, and the no-headers case where the message is left unchanged.

This does not block merging on its own — missing tests don't cause a runtime failure, and the trace-ID feature works correctly as shipped. But it's an explicit, unambiguous violation of a stated project convention, and the parity gap with the JS/Python SDKs (both of which got thorough coverage for the identical logic) makes it worth flagging as a nit for the author to close before merge.

Comment thread packages/cli/src/utils/errors.ts Outdated
Comment on lines +29 to +58
}

/**
* Extract a trace ID from HTTP response headers of a failed request, so the
* error message can carry an ID that E2B support can correlate with
* server-side traces. Checks `X-Trace-ID`, then the GCP
* (`X-Cloud-Trace-Context`) and AWS (`X-Amzn-Trace-Id`) edge trace headers.
*/
function extractTraceId(response?: ResponseHeadersLike): string | undefined {
const headers = response?.headers
if (!headers || typeof headers.get !== 'function') {
return undefined
}

const direct = headers.get('x-trace-id')?.trim()
if (direct) {
return direct
}

// GCP edge: "TRACE_ID/SPAN_ID;o=OPTIONS"
const gcp = headers.get('x-cloud-trace-context')?.split('/')[0]?.trim()
if (gcp) {
return gcp
}

// AWS edge: "Root=1-<8 hex>-<24 hex>;..." — the two hex parts joined are
// the 32-hex trace ID the server logs
const aws = headers.get('x-amzn-trace-id')
if (aws) {
for (const field of aws.split(';')) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 packages/cli/src/utils/errors.ts:37-70 duplicates the exact trace-ID header parsing logic (X-Trace-ID / X-Cloud-Trace-Context / X-Amzn-Trace-Id, including the AWS regex and GCP split) already implemented in packages/js-sdk/src/traceId.ts's extractTraceId. Since the CLI already depends on and imports from 'e2b', consider exporting extractTraceId from js-sdk's public index and importing it here instead of copy-pasting, to avoid the two copies silently drifting on future changes.

Extended reasoning...

What the bug is: packages/cli/src/utils/errors.ts (lines 29-58/37-70) reimplements a byte-for-byte copy of the trace-ID extraction logic that this same PR adds to packages/js-sdk/src/traceId.ts. Both versions check headers in the same priority order — X-Trace-ID (direct, trimmed), X-Cloud-Trace-Context (GCP edge, split('/')[0].trim()), and X-Amzn-Trace-Id (AWS edge, splitting on ;, matching Root=1-<8 hex>-<24 hex> with the identical regex /^1-([0-9a-f]{8})-([0-9a-f]{24})$/i, and joining the two hex groups) — with only the wrapper signature differing (CLI takes a {headers}-shaped object, js-sdk's version takes the Headers object directly).\n\nWhy it happens / code path: This PR introduces extractTraceId/appendTraceId in packages/js-sdk/src/traceId.ts and wires them into packages/js-sdk/src/api/index.ts and packages/js-sdk/src/envd/api.ts. Rather than reusing that helper for the CLI's error handling in packages/cli/src/utils/errors.ts, the PR hand-writes an equivalent extractTraceId function locally. The CLI package already depends on and imports from e2b (see packages/cli/src/api.ts: import * as e2b from 'e2b', and package.json lists e2b: workspace:^), so nothing structurally prevents sharing the implementation — it's purely that extractTraceId is not currently re-exported from js-sdk's public index.ts, which would need to be added for the CLI to import it.\n\nWhy existing code doesn't prevent it: There's no lint rule or test that would catch two independently-written implementations of the same parsing logic living in separate packages; both pass their own test suites (traceId.test.ts for js-sdk, presumably covered indirectly for the CLI) without any cross-check that they stay in sync.\n\nImpact: This doesn't cause incorrect behavior today — both copies are currently identical and produce the same trace IDs. The risk is purely maintenance: any future change to trace-ID parsing (e.g. supporting a new header format, fixing an edge case in the AWS regex, adjusting GCP parsing) has to be applied in two places, and it would be easy to update one copy and forget the other, causing the CLI and SDK to silently disagree on trace IDs for the same failure.\n\nProof (concrete example): Suppose in a follow-up PR someone fixes a bug in the AWS regex — say widening it to accept a 16-hex span ID variant, changing the pattern in packages/js-sdk/src/traceId.ts only (since that's the 'canonical' looking implementation reused by the JS SDK's API/envd handlers). packages/cli/src/utils/errors.ts's local copy still has the old regex. Now: a request fails with an AWS trace header in the new format; the JS SDK correctly extracts and reports the trace ID; the CLI (which wraps the same underlying e2b client and hits the same API) falls through the regex match and falls back to the raw Root=... string (or drops the ID depending on which branch), producing an inconsistent/wrong trace ID for the exact same server-side failure. A user following CLI-reported error output to file a support ticket would give E2B support a malformed or missing trace ID, right where this feature is supposed to help.\n\nHow to fix: Export extractTraceId (and optionally appendTraceId) from js-sdk's public src/index.ts, then in packages/cli/src/utils/errors.ts import it and adapt the call site to pass res.response?.headers directly (a trivial signature bridge, since the CLI's ResponseHeadersLike.headers is already the same {get(name): string|null} shape as js-sdk's HeadersLike), deleting the ~45-line duplicated block entirely.

@mishushakov mishushakov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

reviewed, please remove duplicate method in JS SDK and you can modify the default Error classes to accept a trace field in the constructor that will append it to the message, which is cleaner than relying on helpers side-effects

Comment thread packages/cli/src/utils/errors.ts Outdated

function throwE2BRequestError(error: E2BResponseError, errMsg?: string): never {
type ResponseHeadersLike = {
headers?: { get(name: string): string | null }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

you can use built-in Headers type from undici?

Comment thread packages/js-sdk/src/api/index.ts Outdated
errorClass,
stackTrace
return appendTraceId(
apiErrorFromCode(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

maybe just change apiErrorFromCode instead

Comment thread packages/js-sdk/src/traceId.ts Outdated
* 3. `X-Amzn-Trace-Id` (AWS edge) — `Root=1-<8 hex>-<24 hex>;...`, the two
* hex parts joined are the 32-hex trace ID the server logs.
*/
export function extractTraceId(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this is same code as in packages/cli/src/utils/errors.ts

Comment thread packages/js-sdk/src/traceId.ts Outdated
* Append the trace ID of the failed request to the error message, so users
* can include it when reporting the failure to E2B.
*/
export function appendTraceId<T extends Error | undefined>(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

you could also modify E2B error classes to have trace id in message instead of this

Comment thread packages/python-sdk/e2b/api/__init__.py Outdated
if message is None and e.status_code not in (401, 429):
return default_exception_class(f"{e.status_code}: {e.content}").with_traceback(
stack_trace
return append_trace_id(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

feel free to update default_exception_class instead

Address review feedback:
- Error/exception classes now take an optional trace ID in the
  constructor and append it to the message, instead of a post-hoc
  append helper; apiErrorFromCode / api_exception_from_code and the
  envd error maps thread it through.
- The CLI reuses extractTraceId exported from the JS SDK instead of
  keeping its own copy, and types headers with the built-in Headers.
- Cover AWS raw-value fallback and header priority in the CLI tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0147b6bTi2gq4Yvm7VrLrxLD

djeebus commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the review in 0adc234:

  • Duplicate method removedextractTraceId now lives only in the JS SDK (src/traceId.ts), is exported from the package index, and the CLI imports it from e2b.
  • Trace ID via constructors — the error/exception classes in both SDKs now take an optional trace ID in the constructor and append it to the message (SandboxError(message, stackTrace, traceId) / SandboxException(message, trace_id)); the appendTraceId/append_trace_id side-effect helpers are gone. apiErrorFromCode / api_exception_from_code and the envd error maps thread the trace ID through, per the inline suggestions.
  • Built-in Headers type — the CLI (and the SDK helper) now type headers with the standard Headers instead of a custom shape.

Also added CLI test cases for the AWS raw-value fallback and header priority.


Generated by Claude Code

@mishushakov

Copy link
Copy Markdown
Member

@djeebus Second pass — I re-reviewed after 0adc234 and verified the build locally. All five of my earlier comments are addressed; details plus a few independent findings below.

My earlier comments

Comment Status
Remove duplicate extractTraceId in the CLI ✅ One copy in js-sdk/src/traceId.ts, exported from index.ts, CLI imports from 'e2b'.
Modify default Error classes to take a trace field in the constructor ✅ Both SDKs; appendTraceId/append_trace_id deleted. ⚠️ see B
maybe just change apiErrorFromCode instead ✅ Threads traceId. Extraction staying in handleApiError is right — apiErrorFromCode also serves errors embedded in bodies (per-fork results) and has no response to read.
Use built-in Headers type ✅ Global Headers in both. ⚠️ traceId.ts:12 still runtime-guards typeof headers.get !== 'function' — leftover from the old HeadersLike shape and now unreachable, since the !headers check already covers every mock. Please drop it.
feel free to update default_exception_class instead ✅ Base SandboxException/AuthenticationException/BuildException/VolumeException take trace_id; api_exception_from_code passes it through.

A. The feature is inert against production today, and 2 of its 3 header paths likely never fire

You flagged this in the description and asked someone to verify which header a real failed response returns. I checked against live prod:

Request Result Response headers
GET api.e2b.dev/sandboxes/does-not-exist (no auth) 401 content-type, date, content-length, via, alt-svc
same, with a real API key 400 identical set
GET 49999-<bogus>.e2b.app/files?path=/x (sandbox edge) 502 identical set

No trace header on any path. And via: 1.1 google matters here: X-Cloud-Trace-Context and X-Amzn-Trace-Id are request-side conventions — the LB injects them toward the backend, neither is echoed back on the response. So only X-Trace-ID has a plausible future, and it needs the infra one-liner you described.

Suggestion: land c.Header("X-Trace-ID", traceID) in infra first (or in parallel), and drop the GCP/AWS branches plus the AWS normalization regex and their tests unless we can name a deployment that actually returns them. That's roughly half the new code, and the JS/Python duplication of the AWS parser is the part most likely to drift.

B. JS error-class arity is now inconsistent, and it's a live trap

SandboxError(message, stackTrace?, traceId?) but AuthenticationError(message, traceId?) / GitAuthError(message, traceId?) — trace ID in slot 2 vs slot 3. Meanwhile apiErrorFromCode/handleApiError declare errorClass: new (message, stackTrace?, traceId?) => Error, which AuthenticationError satisfies structurally (fewer params is assignable). Confirmed by construction:

apiErrorFromCode(500, 'boom', AuthenticationError, 'STACK', 'realtrace')
// typechecks clean; message === "500: boom (trace ID: STACK)"

No current call site hits it — handleApiError is only ever passed BuildError/FileUploadError/TemplateError/VolumeError — so it's latent rather than broken, but it's the kind of thing that bites the next person. Python has no equivalent problem; it's uniformly (message, trace_id). Please give AuthenticationError/GitAuthError the same 3-arg shape.

Related: six call sites now read new NotFoundError(message, undefined, traceId). An options bag — new SandboxError(message, { stackTrace, traceId }) — removes the undefined padding and the arity trap in one move, and matches our convention that optional parameters go in a trailing options object. Still a constructor field, so it satisfies the original request.

C. Unrelated change bundled in

VolumeError gained this.stack = stackTrace (errors.ts:182-184), which has nothing to do with trace IDs. It also introduces a JS↔Python divergence: Python's VolumeException.__init__ is (message, trace_id) with no stack-trace param. No caller passes a stack trace to VolumeError (every site is handleApiError(res, VolumeError)), so it's dead today. Drop it, or mirror it in Python.

D. extractTraceId is now public JS API with no Python counterpart

export { extractTraceId } in src/index.ts puts an internal parser on the public e2b surface, while extract_trace_id is absent from e2b/__init__.py. We treat JS/Python parity of the public surface as non-negotiable. The CLI's tsconfig maps only bare e2b../js-sdk/src (no e2b/*), so index was the only zero-config route — that's fine, but it should be a deliberate call, and neither the changeset nor the PR description mentions the new export.

E. Smaller notes

  • SupportsApiErrorResponse not extendedhandle_api_exception reaches for getattr(e, "headers", None), but the generated Response dataclass does declare headers: MutableMapping[str, str], and every real caller (including the hand-built volume ones) passes httpx.Headers. Adding headers to the Protocol would let ty check it.
  • Trace ID silently dropped on empty messages — both formatMessage and format_message_with_trace_id require a truthy message, so new SandboxError(undefined, undefined, 'abc') loses it. Marginal.
  • Connect-RPC paths uncovered — documented as intentional, but that's where most sandbox.commands/sandbox.files errors surface, so the feature won't reach the majority of in-sandbox failures even once infra sets the header. Worth calling out explicitly in the description.
  • No test that a custom errorClass (BuildError/VolumeError) receives the trace ID through handleApiError.
  • Python's _FILESYSTEM_HTTP_ERROR_MAP needed no change (it holds classes, not lambdas) while the JS one did — correct, just asymmetric.

Verification I ran locally

  • Lint/format: js-sdk oxlint clean; ruff check + ruff format --check clean (406 files); prettier --check clean on js-sdk src+tests and cli src.
  • Typecheck: js-sdk tsc --noEmit clean, cli clean, python ty check clean.
  • Tests: js-sdk traceId + handleApiError + handleEnvdApiError → 53 passed. CLI vitest run → 114 passed (only template/create.test.ts fails, which needs E2B_API_KEY; unrelated). Python test_trace_id.py → 20 passed.
  • CI: the single red check, Build Packages, is a transient GitHub 503 while uv downloaded CPython 3.10.19 — unrelated to this PR, just needs a re-run.

Verdict

The feedback was implemented faithfully and the mechanics are sound. Before merge I'd like B fixed (real trap, two-line change) and C dropped. A is the judgment call worth your input: as it stands this ships ~690 lines that produce no trace ID against any live E2B endpoint, and two-thirds of the parsing targets headers that GCP-fronted responses don't carry. Pairing it with the infra header change and cutting the edge-header branches would leave a much smaller, actually-exercised feature.

…ck change

Address second-pass review:
- AuthenticationError/GitAuthError take (message, stackTrace, traceId)
  like the other error classes, closing the arity trap where a custom
  errorClass could receive the stack trace in the trace ID slot.
- VolumeError no longer applies the stack trace, restoring its
  pre-existing behavior; the parameter stays for the errorClass shape.
- Drop the unreachable typeof guard in extractTraceId.
- Export extract_trace_id from the Python package for JS/Python parity
  with the new extractTraceId export, and mention both in the changeset.
- Declare headers on SupportsApiErrorResponse so ty checks the access.
- Cover custom errorClass trace ID pass-through in handleApiError tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0147b6bTi2gq4Yvm7VrLrxLD

djeebus commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

Second-pass items addressed in b7eeae2:

  • B (arity trap)AuthenticationError/GitAuthError now take the same (message, stackTrace?, traceId?) shape as the other classes, so a custom errorClass can no longer receive the stack trace in the trace ID slot. The construction you demonstrated now produces 500: boom (trace ID: realtrace).
  • CVolumeError no longer applies the stack trace (pre-existing behavior restored); the parameter remains only to fit the errorClass constructor shape, with a comment saying so.
  • Leftover guard — the unreachable typeof headers.get check in extractTraceId is gone.
  • D (parity)extract_trace_id is now exported from the Python package (e2b/__init__.py + __all__), and both exports are mentioned in the changeset and PR description.
  • ESupportsApiErrorResponse declares headers (so ty checks the access, getattr dropped); added a handleApiError test for trace ID pass-through with a custom errorClass (BuildError); the PR description now calls out the RPC-path limitation explicitly.

A is @djeebus's call, so I've left the GCP/AWS branches in place for now and updated the PR description with your production findings (no trace header on any live path, via: 1.1 google, request-side conventions). If the decision is to trim to X-Trace-ID-only and pair with the infra c.Header("X-Trace-ID", traceID) change, that's a small follow-up commit — happy to do it on this branch once decided.

Build Packages failure on 0adc234 was the transient 503 you diagnosed; the new push re-runs CI.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants