Skip to content

[P1] client.diesel.* raises pydantic ValidationError on v1.13.0 — envelope unpacked one level too high #110

Closed

Description

@karlwaldman

Summary

client.diesel.get_price() and client.diesel.get_stations() both raise pydantic_core.ValidationError on the published oilpriceapi==1.13.0. Confirmed live against production on 2026-09-13. The Node SDK equivalent works, so this is an SDK-side envelope bug, not an API change.

Repro

python -m pip install oilpriceapi==1.13.0
export OILPRICEAPI_KEY=...
from oilpriceapi import OilPriceAPI
client = OilPriceAPI()
client.diesel.get_price("CA")
pydantic_core._pydantic_core.ValidationError: 7 validation errors for DieselPrice
state    Field required [type=missing, input_value={'regional_average': {'pr...e', 'state_code': 'CA'}}]
price    Field required [type=missing, ...]
currency Field required [type=missing, ...]
unit     Field required [type=missing, ...]
granularity Field required [type=missing, ...]
source   Field required [type=missing, ...]
updated_at Field required [type=missing, ...]

client.diesel.get_stations(lat=37.7749, lng=-122.4194, radius=8047) fails the same way with 4 errors for DieselStationsResponse (regional_average, stations, search_area, metadata all reported missing).

Root cause

GET /v1/diesel-prices?state=CA returns, verified live:

{"status":"success","data":{"regional_average":{"price":8.136,"currency":"USD","unit":"gallon","region":"california","granularity":"state","source":"aaa","updated_at":"2026-09-13T14:57:19Z","cached":true},"sources":{...},"upgrade":{...},"location":{"type":"state","state_code":"CA"}}}

resources/diesel.py (v1.13.0) does:

if "regional_average" in response:
    price_data = response["regional_average"]
elif "data" in response:
    price_data = response["data"]
else:
    price_data = response
return DieselPrice(**price_data)

The first branch misses because regional_average is nested under data, so the second branch fires and hands DieselPrice the whole data object (regional_average/sources/upgrade/location) instead of the record. The correct read is response["data"]["regional_average"].

get_stations has the same shape bug: DieselStationsResponse(**response) should unpack response["data"].

Workaround that does work

with OilPriceAPI(api_key=os.environ["OILPRICEAPI_KEY"]) as client:
    payload = client.request("GET", "/v1/diesel-prices", params={"state": "CA"}, timeout=30)
average = payload["data"]["regional_average"]
# {'price': 8.136, 'currency': 'USD', 'unit': 'gallon', 'region': 'california',
#  'granularity': 'state', 'source': 'aaa', 'updated_at': '2026-09-13T14:57:19Z'}

Suggested test

Fixture the real production envelope (nested under data) rather than a flattened record — the current tests pass because they assert against the flattened shape the SDK expects, not the shape the API sends.

Docs impact

docs/quick-start/python.md shipped both calls as working examples. They are replaced with the client.request() workaround and a warning pointing here, pending an SDK release. Once fixed and released, that page should switch back to the typed helpers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions