Skip to content

fix(batch-evaluation): keep paging past empty observation pages - #2097

Merged
hassiebp merged 2 commits into
langfuse:mainfrom
DavidTraina:fix/batch-eval-empty-observation-pages
Nov 5, 2026
Merged

hassiebp merged 2 commits into
langfuse:mainfrom
DavidTraina:fix/batch-eval-empty-observation-pages

Conversation

@DavidTraina

@DavidTraina DavidTraina commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

Since langfuse/langfuse#19043, GET /api/public/v2/observations can return an empty page that still has meta.cursor. This happens when the server's 45 s scan budget runs out (or a later scan window times out) after at least one window completed without matches. The route adds meta.comment to say so: "This empty page does not indicate completion. Continue requesting pages using meta.cursor."

run_batched_evaluation stopped on if cursor is None or not items:. On such a page it returned completed=True, has_more_items=False and no resume token, so every older observation was skipped without any signal.

Fix

  • Stop only when the cursor is absent.
  • Update previous_page_ids only for pages with items. Otherwise an empty page clears the cross-page dedupe set and the resume token's last_page_ids. test_duplicate_rows_split_across_an_empty_page_are_evaluated_once covers this: a duplicate row on either side of an empty page is scored once.

The loop still terminates: the server returns a strictly lower cursor on every page. Older servers, and servers with LANGFUSE_OBSERVATIONS_V2_ADAPTIVE_SCAN_ENABLED=false, return a cursor only when more rows exist, so nothing changes for them.

With the default 5 s client timeout, most slow pages fail with a client timeout before the server can answer with an empty page. #2096 covers that. Once the timeout is long enough, this bug silently drops data, so the two fixes are independent.

Related PRs

Independent follow-ups to langfuse/langfuse#19043, mergeable in any order: #2096 (batch evaluation fetch timeout), #2098 (docs), #2099 (test helpers), #2101 (pagination helper).

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Refactor
  • Documentation update
  • Tooling, CI, or repo maintenance

Verification

List the main commands you ran:

uv run --frozen ruff check .                                  # All checks passed!
uv run --frozen ruff format --check .                         # 593 files already formatted
uv run --frozen mypy langfuse --no-error-summary              # no issues
uv run --frozen pytest -n auto --dist worksteal tests/unit    # 1005 passed, 2 skipped
# The new test fails on main: assert [None, '2'] == [None, '2', '2', '4']
uv run --frozen pytest tests/unit/test_batch_evaluation.py::test_empty_page_with_cursor_does_not_end_the_run

Checklist

  • I self-reviewed the diff using code_review.md.
  • I added or updated tests for behavior changes.
  • I updated docs, examples, or .env.template if needed.
  • I did not hand-edit generated files; if generated files changed, I used the upstream regeneration path.
  • I did not commit secrets or credentials.

RetriggerView in GreptileConfidence Score: 4/5

The PR appears safe to merge, with a non-blocking test gap around keeping IDs across empty pages.

Summary

Batch evaluation now continues past empty observation pages when meta.cursor is present.

  • Batch evaluation keeps paging after an empty page with a cursor.

Reviews (1) · Last reviewed commit: "fix(batch-evaluation): keep paging past ..." · Reviewed by Greptile

Since langfuse/langfuse#19043, GET /api/public/v2/observations can return
an empty page with meta.cursor set when its scan deadline passes. The run
stopped on any empty page and reported itself complete with no resume
token, silently skipping the remaining observations. Stop only when the
cursor is absent, and keep the cross-page dedupe state across empty pages.

@claude claude 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.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

Comment thread tests/unit/test_batch_evaluation.py Resolved
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@hassiebp
hassiebp enabled auto-merge (squash) November 5, 2026 09:08
@hassiebp
hassiebp merged commit 3a07303 into langfuse:main Nov 5, 2026
21 checks passed
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.

3 participants