Skip to content

fix(platform)!: drop inert OData params from list_records - #1877

Merged
avichalsri24 merged 3 commits into
mainfrom
fix/entities-list-records-drop-odata-params
Sep 1, 2026
Merged

fix(platform)!: drop inert OData params from list_records#1877
avichalsri24 merged 3 commits into
mainfrom
fix/entities-list-records-drop-odata-params

Conversation

@avichalsri24

Copy link
Copy Markdown
Contributor

Problem

EntitiesService.list_records advertises OData filtering:

filter (Optional[str]): OData $filter expression (e.g. "status eq 'active'")

The endpoint it calls — GET datafabric_/api/EntityService/entity/{key}/read — does not implement it. It accepts $filter, $orderby, $select and $expand, ignores them, and returns the full unfiltered set. The failure mode is a silent wrong answer: a filtered query returns every record, with no error.

Verified against a live tenant (TestEntity, 32 records), via the SDK and raw httpx:

Request Result
no params 32 records
$filter=Name eq '<one real match>' 32 records
$filter=Name eq 'definitely-no-such-value-xyz' 32 records
$filter=bogus syntax ((( HTTP 200, 32 records
$select=Name 32 records, all 7 columns
$orderby=Name desc order unchanged
filter=… (no $) / query=… 32 records

What the endpoint does honour:

Param Honoured Evidence
start yes start=30 → 2 of 32; start=100 → 0
limit yes 1/2/31 → exact; 1000 → 32; 0 → 32 (treated as unset); -1 → HTTP 400 Invalid limit -1
expansionLevel yes 0 → bare guid, 1{Id}, 2 → full nested record

GET api/v2/.../read returns 404, so there is no newer read endpoint these params were written against.

Why CI didn't catch it

The four params were added in #1616 alongside the (working) structured query API. The covering test asserted only that pytest-httpx received them:

assert params.get("$filter") == "status eq 'active'"
assert params.get("$orderby") == "name asc"

That passes whether or not the server implements any of it — the mock replies with whatever the test told it to.

Change

Remove filter, orderby, select and expand from list_records / list_records_async and from _list_records_spec. This restores the pre-#1616 parameter surface (entity_key, schema, start, limit) plus expansion_level, which does work — nothing that ever functioned is lost.

Filtering, sorting and projection already have a working home in retrieve_records (POST .../query, EntityQueryFilterGroup); docstrings and examples now point there. _list_records_spec records why the params are not sent, so they don't get re-added.

The test now asserts the positive contract and the negative one:

assert params.get("start") == "0"
assert params.get("limit") == "3"
assert params.get("expansionLevel") == "2"
assert [key for key in params if key.startswith("$")] == []

Note for reviewers: filtering a related entity's field via retrieve_records needs field_name="Rel.Id" and expansion_level>=1, otherwise the backend rejects it with "Filtering or sorting fields from related entities has to be expanded in the query". Filtering on the bare relationship name (CreatedBy eq '<guid>') is silently ignored — same class of trap, on the endpoint that otherwise works.

Verification

Live tenant, with this branch's source:

limit=2, expansion_level=2 -> returned=2 total=32
  CreatedBy expanded to: <full nested SystemUser record>
start=30                   -> returned=2 total=32
filter=…                   -> TypeError: got an unexpected keyword argument 'filter'

uipath-platform suite passes, ruff check / ruff format --check clean, mypy src clean (163 files).

Breaking change

list_records() / list_records_async() no longer accept filter, orderby, select or expand. Passing them raises TypeError instead of silently returning unfiltered records. Callers migrate to retrieve_records() with an EntityQueryFilterGroup.

Happy to swap this for a deprecation window (keep the params, raise NotImplementedError) if reviewers prefer a softer landing.

🤖 Generated with Claude Code

The Data Fabric read endpoint (GET .../EntityService/entity/{key}/read)
implements only start, limit and expansionLevel. It accepts $filter,
$orderby, $select and $expand, then silently ignores them and returns the
full unfiltered set. Verified against a live tenant: a filter matching
nothing still returned all 32 records, as did deliberately malformed
filter syntax, and $select left every column in place. There is no v2
read endpoint that honours them.

The four params were added in #1616 alongside the structured query API.
Their test asserted only that httpx received them under a mock, so it
could not catch that the server drops them. The docstring advertised
them as OData support, making the failure mode a silent wrong answer:
a filtered query returning every record.

Remove them, restoring the pre-#1616 surface plus expansion_level, which
does work. Filtering, sorting and projection belong to retrieve_records
(POST .../query), which genuinely filters.

BREAKING CHANGE: list_records() and list_records_async() no longer accept
filter, orderby, select or expand. Passing them now raises TypeError
instead of silently returning unfiltered records. Use retrieve_records()
with an EntityQueryFilterGroup instead.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 1, 2026 08:54
@github-actions github-actions Bot added test:uipath-langchain Triggers tests in the uipath-langchain-python repository test:uipath-integrations labels Sep 1, 2026

Copilot AI 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.

🟡 Changes recommended

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR removes OData-related parameters from EntitiesService.list_records / list_records_async in uipath-platform because the underlying Data Fabric /read endpoint accepts those params but silently ignores them, creating a “silent wrong answer” failure mode. The change narrows the public API to the parameters the endpoint actually honors (paging + expansion), updates documentation/examples to route filtering/sorting/projection to the structured query API, and adjusts tests accordingly.

Changes:

  • Drop inert filter, orderby, select, expand kwargs from sync/async list_records and from the internal request spec builder.
  • Update docs/examples to point filtering/sorting/projection to retrieve_records (POST .../query) instead of list_records.
  • Update unit test assertions to ensure only paging/expansion params are sent; bump uipath-platform version.
File summaries
File Description
packages/uipath-platform/src/uipath/platform/entities/_entity_data_service.py Removes OData kwargs from internal list methods/spec; documents why OData params are not sent.
packages/uipath-platform/src/uipath/platform/entities/_entities_service.py Removes OData kwargs from the public facade; updates docstrings/examples to use retrieve_records.
packages/uipath-platform/tests/services/test_entities_service.py Updates the list-records test to assert only paging/expansion params are sent.
packages/uipath-platform/pyproject.toml Bumps the uipath-platform package version.
Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/uipath-platform/tests/services/test_entities_service.py
Comment thread packages/uipath-platform/pyproject.toml
avichalsri24 and others added 2 commits September 1, 2026 14:30
The lint jobs run `uv sync --locked`, which fails while the lockfiles
still pin uipath-platform 0.2.22. Only the version line is touched in
each lock — `uv lock --check` passes on both.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
Addresses review feedback: the wire-level assertion showed no $-params are
sent, but nothing pinned the caller-facing contract. Parametrized test
asserts filter/orderby/select/expand each raise TypeError, so the params
cannot quietly return — including via a future **kwargs.

Also corrects the section header above list_records, which still described
the method as a "multi-record read with OData filters".

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>

Copilot AI 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.

🟢 Approval recommended

Review details
  • Files reviewed: 4/6 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@sonarqubecloud

sonarqubecloud Bot commented Sep 1, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

🚨 Heads up: uipath-langchain cross-tests are FAILING 🚨

Your changes may break the uipath-langchain-python integration.

⚠️ These checks are NOT enforced by branch protection rules. Please review the failures before merging.

🔍 Inspect the failed run →

@avichalsri24
avichalsri24 merged commit 2da6af2 into main Sep 1, 2026
162 of 178 checks passed
@avichalsri24
avichalsri24 deleted the fix/entities-list-records-drop-odata-params branch September 1, 2026 10:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:uipath-integrations test:uipath-langchain Triggers tests in the uipath-langchain-python repository

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants