Skip to content

fix(local): reject offset with order_by before the empty-collection fast path - #1458

Open
feiiiiii5 wants to merge 1 commit into
qdrant:devfrom
feiiiiii5:fix/local-scroll-offset-order-by-empty
Open

feiiiiii5 wants to merge 1 commit into
qdrant:devfrom
feiiiiii5:fix/local-scroll-offset-order-by-empty

Conversation

@feiiiiii5

Copy link
Copy Markdown
Contributor

Problem

In local mode, scroll() with order_by and offset behaves differently depending on whether the collection happens to contain any points:

from qdrant_client import QdrantClient, models

client = QdrantClient(":memory:")
client.create_collection("c", vectors_config=models.VectorParams(size=2, distance=models.Distance.DOT))

client.scroll("c", limit=3, order_by=models.OrderBy(key="k"), offset=1)
# before this change: ([], None)          <- empty collection
# after one upsert:   ValueError: Offset is not supported in conjunction with `order_by` scroll parameter

The server rejects the order_by + offset combination before it looks at stored points, and local mode does too — but only once a point exists, so a caller sees a successful empty page on an empty collection and the documented error on the identical call later.

Cause

LocalCollection.scroll() returns early for an empty collection:

if len(self.ids) == 0:
    validate_filter(scroll_filter, allow_jsonesque=True)  # "to have the same behaviour as the server"
    return [], None

That branch deliberately keeps server-side argument validation on the empty path, but the offset/order_by guard sits further down, inside the order_by section (previously at local_collection.py:2120), so the early return pre-empts it.

Change

Hoist the guard to the top of scroll(), so the request is rejected before the empty-collection fast path, the same way validate_filter already is. Behavior for offset without order_by (which is supported) is untouched, and local_collection.py has no generated async twin, so nothing needs regenerating.

Testing

New regression test qdrant_client/local/tests/test_scroll_validation.py runs the identical call against an empty and a non-empty collection:

(cd repo root) python -m pytest qdrant_client/local/tests/test_scroll_validation.py -q
  • pristine 589a87a: 1 failed, 1 passed — the empty-collection case fails, which is the bug.
  • this branch: 2 passed.

Wider local suites at head: python -m pytest qdrant_client/local/tests tests/test_in_memory.py -q145 passed.

Repo gates on the changed files: ruff format --check --line-length=992 files already formatted; ruff checkAll checks passed!.

Notes for the reviewer

  • local_collection.py is hand-written (not generated), so there is no async twin to regenerate, and the diff is the 5-line move plus the test.
  • Targeting dev as the template asks.
  • This PR was prepared with an AI assistant; I reviewed the diff and ran the commands above locally. Remote CI on a fork PR may still be awaiting maintainer approval, so the numbers here are local.

The empty-collection fast path in LocalCollection.scroll returned an empty
page before the offset/order_by guard, so the same misconfigured scroll only
raised once the collection held a point. Move the guard above the fast path so
local mode rejects the combination the way the server does, regardless of data.
@netlify

netlify Bot commented Sep 20, 2026

Copy link
Copy Markdown

Deploy Preview for poetic-froyo-8baba7 ready!

Name Link
🔨 Latest commit c998abb
🔍 Latest deploy log https://app.netlify.com/projects/poetic-froyo-8baba7/deploys/6aafc0ecafc4080008b4bcca
😎 Deploy Preview https://deploy-preview-1458--poetic-froyo-8baba7.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Sep 20, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: d7b959c1-d152-4158-ae64-504f2f4dba30

📥 Commits

Reviewing files that changed from the base of the PR and between 589a87a and c998abb.

📒 Files selected for processing (2)
  • qdrant_client/local/local_collection.py
  • qdrant_client/local/tests/test_scroll_validation.py

Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

scroll now validates the incompatible order_by and offset combination before handling empty collections or selecting a scrolling implementation. The duplicate validation in the value-ordered path was removed. A parameterized test verifies the ValueError for both empty and populated collections.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Low

Suggested reviewers: joein

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly explains the local scroll validation bug, the code change, and the regression tests. It directly relates to the changeset.
Title check ✅ Passed The title clearly and concisely identifies the main change: rejecting offset with order_by before the empty-collection fast path.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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