Skip to content

fix: run post execute hooks when stream_result fails before streaming - #968

Merged
elijahbenizzy merged 1 commit into
apache:mainfrom
digit50:fix/langfuse-stream-result-call-post
Oct 17, 2026
Merged

elijahbenizzy merged 1 commit into
apache:mainfrom
digit50:fix/langfuse-stream-result-call-post

Conversation

@digit50

@digit50 digit50 commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

closes #967

stream_result and astream_result call the pre_run_execute_call hook first, then process the control flow parameters, validate the halt conditions and fast-forward with run(), but only the later try block calls the post hook on an error. When anything in that early section raised (an action failing during the fast-forward, or an unknown halt_after name), post_run_execute_call never ran, so LangfuseBridge left its root span and its Langfuse propagate_attributes context attached. Later spans in the same context landed in the failed call's trace with its session and user ids, and the same app's next run() emitted no run span because the app id stayed registered.

Changes

  • In Application.stream_result and Application.astream_result, the section between the pre hook and the existing try is wrapped so that an exception calls call_post / acall_post with that exception and is then re-raised. This matches what a failing run() already does. The rest of the diff in application.py is the indentation that comes with the wrap.
  • No change to the Langfuse bridge itself.

How I tested this

  • Added test_langfuse_bridge_stream_result_failure_closes_trace (parametrized over a failing fast-forward and an unknown halt_after name) and test_langfuse_bridge_astream_result_failure_closes_trace to tests/integrations/test_burr_langfuse.py. They use the graph from the issue (a -> b, where a raises) and check that the stream_result root span is ended with an error status, that no span is still current, that the Langfuse attribute context has been exited, and that the same app's next run() emits its own run root with no parent. All three fail on main (the stream_result span is never exported) and pass with the change.
  • pytest tests/integrations/test_burr_langfuse.py: 12 passed.
  • pytest tests/core: 396 passed, 4 failed, identical with and without the change. The 4 failures are test_graphviz_display.py::test_visualize_dot_output, which needs the Graphviz dot executable that is not installed on my machine.
  • The reproduction script from the issue now prints the expected output for all three cases.

Notes

The ordering in stream_result predates the Langfuse integration, so any lifecycle hook that pairs pre_run_execute_call with post_run_execute_call (for example the OpenTelemetry bridge) was also missing its post call on these failures.

Checklist

  • PR has an informative and human-readable title (this will be pulled into the release notes)
  • Changes are limited to a single goal (no scope creep)
  • Code passed the pre-commit check & code is left cleaner/nicer than when first encountered.
  • Any change in functionality is tested
  • New functions are documented (with a description, list of inputs, and expected output)
  • Placeholder code is flagged / future TODOs are captured in comments
  • Project documentation has been updated if adding/changing functionality.

stream_result and astream_result called the pre execute hook before validating halt conditions and fast-forwarding, but only called the post hook on errors raised later. A failure in that early section left the LangfuseBridge root span and its propagate_attributes context attached. The early section now calls the post hook with the exception before re-raising.
@github-actions github-actions Bot added the area/core Application, State, Graph, Actions label Oct 16, 2026

@elijahbenizzy elijahbenizzy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM. Checked that the success-path hook order is identical to main and the post hook fires once; the _run_call_var guard makes the except path safe. Thanks for the parametrized repro. Elijah

@elijahbenizzy
elijahbenizzy enabled auto-merge (squash) October 17, 2026 15:27
@elijahbenizzy
elijahbenizzy merged commit b575283 into apache:main Oct 17, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/core Application, State, Graph, Actions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

LangfuseBridge leaks root span and session context when stream_result fails

2 participants