Skip to content

types: don't crash ResponseError on non-object JSON error bodies - #788

Open
AP24110011695 wants to merge 1 commit into
ollama:mainfrom
AP24110011695:fix/response-error-non-dict-json
Open

AP24110011695 wants to merge 1 commit into
ollama:mainfrom
AP24110011695:fix/response-error-non-dict-json

Conversation

@AP24110011695

Copy link
Copy Markdown

Problem

A non-2xx response whose body is valid JSON but not an object crashes ResponseError construction with AttributeError instead of raising the error:

AttributeError: 'NoneType' object has no attribute 'get'   # body: null
AttributeError: 'list' object has no attribute 'get'       # body: []

ResponseError.__init__ wraps json.loads(error).get('error', error) in contextlib.suppress(json.JSONDecodeError), which only guards the parse step — calling .get() on a parsed null / list / string / number raises AttributeError that escapes the suppress. Verified on main (35d9667) by constructing ResponseError('null', 502) and by driving both clients against a local HTTP server returning 502 with such bodies.

The official server always answers with {"error": ...}, but this client is pointed at many Ollama-compatible backends, gateways and proxies whose error pages are frequently bare JSON null / arrays / strings. The crash masks the real HTTP failure (status code and body) and breaks except ollama.ResponseError handling in user code.

Fix

Only extract error when the parsed body is a dict; every other JSON shape falls back to the raw body — exactly the existing fallback for non-JSON bodies. Dict-body behavior (including the missing-error-key fallback) is unchanged.

Tests

Parametrized regression tests in tests/test_client.py over a real local HTTP server returning 502, covering dict, null, [], and quoted-string bodies through both client paths:

  • test_client_response_error_json_body_shapes
  • test_async_client_response_error_json_body_shapes

On main (35d9667) the six non-dict cases fail with AttributeError and the two dict cases pass; with this change all 8 pass. Full tests/test_client.py + tests/test_type_serialization.py + tests/test_systemone.py: 107 passed, no new failures (the 8 Image/create_blob failures present locally fail identically on clean main on this Windows machine and are unrelated). ruff check + ruff format --check clean on both touched files.

A non-2xx response whose body is valid JSON but not an object (null, a
list, a quoted string, a number - common for gateway/proxy error
pages) crashed ResponseError construction with AttributeError instead
of raising the error: contextlib.suppress only guarded JSONDecodeError,
so json.loads(...).get() blew up on non-dict values.

Only extract 'error' when the parsed body is a dict; every other JSON
shape falls back to the raw body, matching the existing non-JSON
fallback. Regression tests cover both client paths with dict, null,
list, and string bodies.

This branch has not been deployed

No deployments
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