Skip to content

fix: always send required freeOnly on price constraint - #7

Merged
filippofinke merged 1 commit into
mainfrom
fix/price-constraint-freeonly
Jun 30, 2026
Merged

filippofinke merged 1 commit into
mainfrom
fix/price-constraint-freeonly

Conversation

@filippofinke

Copy link
Copy Markdown
Owner

Summary

Price-range searches (.price({ min, max })) failed with HTTP 422 GRAPHQL_VALIDATION_FAILED at path prices[0].freeOnly. Root cause: the tutti GraphQL input type ListingPriceConstraint declares freeOnly as a required non-null Boolean, but SearchBuilder.price() only spread the caller's {min,max} and omitted it.

HTTP 422 Unprocessable Entity: {"errors":[{"message":"Internal Server Error","path":["variable","constraints","prices",0,"freeOnly"],...,"code":"GRAPHQL_VALIDATION_FAILED"}],"data":null}

.freeOnly() worked because it set the field explicitly; .price() did not.

Root cause (verified, not inferred)

Decompiled app ListingPriceConstraint input adapter:

  • freeOnly:Z (primitive boolean) + checkNotNull → required, always written
  • key: String! → required
  • min / max → Optional<Double> → optional

Real input shape:

input ListingPriceConstraint { freeOnly: Boolean!, key: String!, min: Float, max: Float }

Changes

  • src/search/builder.ts — default freeOnly: false in .price() (before the spread, so an explicit value still wins)
  • src/core/types.ts — make freeOnly required on PriceConstraint so the omission can't recur; comment cites the adapter
  • README.md — price shape is now verified against the decompiled adapter (removed from the "inferred" caveat)

Verification

Fake-transport check of the variables .fetch() sends:

PASS price({max}):     {"key":"price","freeOnly":false,"max":5000}
PASS price({min,max}): {"key":"price","freeOnly":false,"min":100,"max":5000}
PASS freeOnly():       {"key":"price","freeOnly":true}

The tutti GraphQL input type ListingPriceConstraint declares freeOnly as a
required non-null Boolean (freeOnly:Z + checkNotNull in the app's Kotlin
ListingPriceConstraint input adapter); min/max are optional.

SearchBuilder.price() only spread the caller's {min,max}, omitting freeOnly,
so any price-range filter was rejected by the server with:

  HTTP 422 GRAPHQL_VALIDATION_FAILED at path prices[0].freeOnly

Default freeOnly to false in .price() (before the spread, so an explicit
value still wins) and make freeOnly required on the PriceConstraint type so
the omission can't recur. Update the README caveat: the price shape is now
verified against the decompiled adapter rather than inferred.
@filippofinke
filippofinke merged commit e5cd6c5 into main Jun 30, 2026
1 check passed
@filippofinke
filippofinke deleted the fix/price-constraint-freeonly branch June 30, 2026 12:27
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