Skip to content

Unknown orderBy field returns 400 instead of handled 500 - #1281

Merged
donaldgray merged 2 commits into
developfrom
hygiene/dis-06
Aug 19, 2026
Merged

Unknown orderBy field returns 400 instead of handled 500#1281
donaldgray merged 2 commits into
developfrom
hygiene/dis-06

Conversation

@tomcrane

Copy link
Copy Markdown
Contributor

What does this change?

Fixes #1280.

The orderBy / orderByDescending values on asset collection endpoints (space images, /allImages, batch assets) were not validated: the value was PascalCased and fed straight into Expression.PropertyOrField, so a field name that is not a database-backed asset property threw at runtime and surfaced to the client as a handled 500 "Unexpected error" — for what is a client mistake.

Now AssetQueryX validates the resolved field name against a case-insensitively keyed set of orderable Asset properties, built once by reflection: scalar columns and primitive-collection columns (manifests, deliveryChannels — these are array columns Postgres can order by), excluding collections of related entities (adjuncts, batchAssets, ...). An unknown or unorderable name now throws BadRequestException, which the existing exception filter turns into a clean Hydra 400 with detail Cannot order by field '{value}'.

Everything that ordered successfully before still does, with unchanged semantics — the whitelist is deliberately permissive (any database-backed property) rather than a curated subset, so this PR only converts failures, it doesn't narrow the working surface. Case-insensitive matching (orderBy=WIDTH) is preserved.

One deliberate behaviour change beyond the 500→400: values shorter than 2 characters were previously silently ignored (results quietly ordered by created); they now go through the same validation, so orderBy=x is a 400 too. The old length check existed only to guard the PascalCasing and hid client mistakes.

Ordering of spaces (/customers/{id}/spaces?orderBy=) is a separate hardcoded implementation that silently ignores unknown fields rather than erroring — not touched here.

Integration tests cover: four invalid names → 400 with the expected detail (including imageService, a Hydra-model property that is not a database column, and adjuncts, an entity-collection navigation); valid names → 200 (including WIDTH for case-insensitivity and manifests for primitive-collection ordering).

Breaking Changes

Caution

This PR introduces breaking changes.

Service Description Notes
API GET asset collections with an unknown orderBy/orderByDescending field now return 400 (previously a handled 500 "Unexpected error") Space images, /allImages, batch assets
API orderBy values shorter than 2 characters now return 400 (previously silently ignored, results ordered by created)

🤖 Generated with Claude Code

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@donaldgray
donaldgray marked this pull request as ready for review August 19, 2026 14:25
@donaldgray
donaldgray requested a review from a team as a code owner August 19, 2026 14:25
* Make mapped metadata properties case-insensitive
* Extended reflection used to determine acceptable properties as it
missed some readonly and [NotMapped], which would result in 500
* Use HashSet rather than dictionary as case cleaner
* Move private fields above public methods
* Reduce expression builder as nested properties are blocked
@donaldgray
donaldgray merged commit 23254f5 into develop Aug 19, 2026
8 checks passed
@donaldgray
donaldgray deleted the hygiene/dis-06 branch August 19, 2026 15:19
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.

Unknown orderBy field returns a handled 500 instead of a 400

2 participants