# M12.5B — Qdrant HTTP Semantics and Safe Vision Gateway Errors ## Old behavior Qdrant 4xx (including 422 for `limit > 100`) was rewritten to **Gateway 502**. Public `detail` included the internal URL and raw downstream body. ## New behavior (Qdrant routes only) | Downstream | Gateway | | --- | --- | | 2xx | unchanged JSON | | 400–499 | **same status**, `detail`: `Vector service rejected the request.` | | 500–599 | **502**, `detail`: `Vector service unavailable.` | | transport failure | **502**, sanitized | | 2xx non-JSON | **502**, sanitized | CLIP / BLIP / YOLO / Maturity / Card Renderer / LLM still use the previous helper default (`preserve_client_errors=False`). ## Scope Opt-in via `preserve_client_errors=True, upstream_name="qdrant"` on Qdrant `_post_json` / `_post_file` / `_get_json` / `_delete_json` calls only. ## Deploy (do not run unless requested) ```bash cd /opt/docker/vision docker compose build gateway docker compose up -d --no-deps gateway ``` Do not `docker compose down`. Do not recreate qdrant-svc. ## Rollback Restore previous `gateway/main.py`, then the same build + `--no-deps gateway` up. ## Acceptance (read-only) `POST /vectors/search` `limit=100` → **200**. `limit=101` → **422** (not 502). Body must not contain `qdrant-svc` or Qdrant validation JSON.