Skip to content

fix(auto-instrumentation): Fully preserve returned promise in tracing channel hook#1617

Draft
Luca Forstner (lforst) wants to merge 1 commit intomainfrom
lforst/fix-issue-1592
Draft

fix(auto-instrumentation): Fully preserve returned promise in tracing channel hook#1617
Luca Forstner (lforst) wants to merge 1 commit intomainfrom
lforst/fix-issue-1592

Conversation

@lforst
Copy link
Member

@lforst Luca Forstner (lforst) commented Mar 20, 2026

Fix the auto-instrumentation node hook so Anthropic messages.stream() keeps working under node --import braintrust/hook.mjs.

  • Preserve the original promise-like return value in the hook instead of returning a chained promise
  • Keep Anthropic APIPromise helpers like withResponse() intact
  • Remove the e2e workaround so the Anthropic node-hook scenario uses messages.stream() again
  • Add regression coverage for promise subclass helper preservation

Fixes #1591

Copy link
Contributor

@Qard Stephen Belanger (Qard) left a comment

Choose a reason for hiding this comment

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

This change would be incorrect though. It also breaks behavioural compatibility with Node.js core.

}
},
);
return result;
Copy link
Contributor

Choose a reason for hiding this comment

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

The problem with doing this though is that we'd be silencing unhandledRejection events due to branching and ignoring failures rather than passing through and re-raising the error for the downstream consumer.

Copy link
Member Author

Choose a reason for hiding this comment

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

I had the same thought actually. I am wondering though, is there any way to preserve exact Node.js behavior while also preserving the "extended" promise?

Can we throw inside the error callback?

Copy link
Contributor

Choose a reason for hiding this comment

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

It's a bug on their part for not preserving the promise species correctly. Unsure if there's a way we can hack around it as correct species use also requires retaining the constructor signature for it to be able to correctly construct descendants, but Anthropic violated that contract and gave it a different constructor signature which makes species construction crash. 😐

return result;
} catch (err) {
context.error = err;
error?.publish(context);
publishRejected(err);
Copy link
Contributor

Choose a reason for hiding this comment

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

This is incorrect as if it reaches here it did not run the async portion and so should not produce asyncStart and asyncEnd events.

@lforst Luca Forstner (lforst) marked this pull request as draft March 20, 2026 12:23
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.

Auto-instrumentation via node hook breaks OpenAI helper APIs (parse/withResponse/stream helpers)

2 participants