Fix Anthropic 400 on structured output: strip unsupported JSON-schema range keywords#52
Conversation
… range keywords Anthropic's structured-output validator rejects numeric-range keywords (minimum/maximum/exclusiveMinimum/exclusiveMaximum/multipleOf) on integer types, returning HTTP 400 "For 'integer' type, properties maximum, minimum are not supported". Pydantic emits these from Field(ge=, le=), so the sourcehunt ranker's RankedFileScore (surface/influence scored 1..5) 400s on every call, leaving 0 files ranked and 0 hunted. Recursively strip those keywords from the generated schema in _json_spec_from_model before handing it to genai-pyo3. The bounds are advisory for the model anyway (the prompt states the 1-5 range). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks for tracking this down @amsclark — the root-cause writeup is spot on. I went with a slightly different fix in #54: instead of stripping the range keywords from the generated schema, express the score as a Could you confirm #54 resolves the ranker 400 on your end (the |
Fixes #50.
Problem
Anthropic's structured-output JSON-schema validator rejects numeric-range keywords (
minimum/maximum/exclusiveMinimum/exclusiveMaximum/multipleOf) on integers:_json_spec_from_modelserializes a Pydantic model's schema verbatim, andRankedFileScoreusesField(ge=1, le=5)for itssurface/influencescores — which Pydantic emits as{"type":"integer","minimum":1,"maximum":5}. So the sourcehunt ranker 400s on every call, leaving 0 files ranked and 0 hunted against the Anthropic adapter.Fix
Recursively strip those unsupported keywords from the generated schema in
_json_spec_from_modelbefore handing it togenai-pyo3. The bounds are advisory for the model anyway (the ranker prompt already states the 1–5 range), and callers can clamp post-parse if strictness is wanted.Verification
tests/test_native_schema_compat.py(top-level + nested/array bounds stripped, non-range structure preserved) — no network.clearwing sourcehunt --depth standardon a small planted-vuln C repo now ranks and hunts correctly (previously: "Ranker LLM call failed", 0 findings; after: both planted bugs found, one with an ASan crash reproduction).