Python 88.3%
TypeScript 7.6%
Shell 4.1%
1"""Cheap deliberate-error smoke tests for the OpenAI API (all requests are rejected before any generation => $0).2Also unit-tests examples/shared/errors/classify_error.py against bodies captured live on 2026-09-18.3Run: .venv/bin/pytest -q tests/openai/test_errors.py4"""5from __future__ import annotations67import sys8from pathlib import Path910import pytest1112ROOT = Path(__file__).resolve().parents[2]13sys.path.insert(0, str(ROOT / "examples/shared/errors"))14from classify_error import classify # noqa: E402151617def _err(body):18 assert isinstance(body, dict) and "error" in body, body19 return body["error"]202122def test_invalid_api_key_401(openai):23 st, body, _ = openai("GET", "/v1/models", extra_headers={"Authorization": "Bearer sk-invalid"}, note="test_errors invalid key")24 assert st == 40125 e = _err(body)26 assert e["code"] == "invalid_api_key" and e["type"] == "invalid_request_error"27 assert classify("openai", st, body).category == "auth"282930def test_model_not_found_404(openai):31 st, body, _ = openai("POST", "/v1/responses", {"model": "does-not-exist-model", "input": "Reply with OK.", "max_output_tokens": 16}, note="test_errors model_not_found")32 assert st == 404 and _err(body)["code"] == "model_not_found"33 c = classify("openai", st, body)34 assert c.category == "not_found" and not c.retryable353637def test_invalid_type_400(openai):38 st, body, _ = openai("POST", "/v1/responses", {"model": "gpt-5.4-nano", "input": "Reply with OK.", "max_output_tokens": "sixteen"}, note="test_errors invalid_type")39 assert st == 400 and _err(body)["code"] == "invalid_type" and _err(body)["param"] == "max_output_tokens"404142def test_missing_required_parameter_400(openai):43 st, body, _ = openai("POST", "/v1/responses", {"input": "Reply with OK."}, note="test_errors missing model")44 assert st == 400 and _err(body)["code"] == "missing_required_parameter" and _err(body)["param"] == "model"454647def test_invalid_json_400(openai):48 st, body, _ = openai("POST", "/v1/responses", data=b'{"model": ', note="test_errors invalid json")49 assert st == 400 and _err(body)["code"] == "invalid_json"505152def test_unknown_url_404_has_empty_body(openai):53 st, body, hdrs = openai("GET", "/v1/this_endpoint_does_not_exist", note="test_errors unknown url")54 assert st == 40455 assert body in (b"", "", None) or body == b""56 assert not any(k.lower() == "x-request-id" for k in hdrs) # edge 404: no request id57 assert classify("openai", st, body, hdrs).category == "not_found"585960def test_response_not_found_404(openai):61 st, body, _ = openai("GET", "/v1/responses/resp_000000000000000000000000000000", note="test_errors response 404")62 assert st == 404 and _err(body)["type"] == "invalid_request_error"636465def test_admin_scope_403_bare_string(openai):66 """Admin endpoints answer 403 with `error` as a bare string when the key lacks api.management.read."""67 st, body, _ = openai("GET", "/v1/organization/projects?limit=1", note="test_errors admin 403 shape")68 if st == 200:69 pytest.skip("an Admin key is configured; restriction not reproducible")70 assert st == 403 and isinstance(body["error"], str) and "Missing scopes" in body["error"]71 c = classify("openai", st, body)72 assert c.category == "permission" and not c.retryable737475# ---------------- offline classifier matrix (captured shapes) ----------------76@pytest.mark.parametrize("status,body,category,retryable", [77 (401, {"error": {"message": "Incorrect API key provided", "type": "invalid_request_error", "param": None, "code": "invalid_api_key"}}, "auth", False),78 (403, {"error": "You have insufficient permissions for this operation. Missing scopes: api.management.read."}, "permission", False),79 (403, {"error": {"message": "blocked", "type": "invalid_request_error", "param": None, "code": "misalignment_policy_violation"}}, "safety", False),80 (404, {"error": {"message": "The model `x` does not exist", "type": "invalid_request_error", "param": None, "code": "model_not_found"}}, "not_found", False),81 (404, b"", "not_found", False),82 (400, {"error": {"message": "Unknown parameter: 'x'.", "type": "invalid_request_error", "param": "x", "code": "unknown_parameter"}}, "bad_request", False),83 (422, {"error": {"message": "unprocessable", "type": "invalid_request_error", "param": None, "code": None}}, "bad_request", True),84 (429, {"error": {"message": "Rate limit reached", "type": "rate_limit_error", "param": None, "code": "rate_limit_exceeded"}}, "rate_limit", True),85 (429, {"error": {"message": "slow down", "type": "rate_limit_error", "param": None, "code": "slow_down"}}, "rate_limit", True),86 (429, {"error": {"message": "quota", "type": "insufficient_quota", "param": None, "code": "insufficient_quota"}}, "quota_billing", False),87 (429, {"error": {"message": "spend", "type": "insufficient_quota", "param": None, "code": "project_spend_limit_exceeded"}}, "quota_billing", False),88 (500, {"error": {"message": "server had an error", "type": "server_error", "param": None, "code": None}}, "server", True),89 (503, {"error": {"message": "overloaded", "type": "service_unavailable_error", "param": None, "code": "server_is_overloaded"}}, "server", True),90 (None, None, "network", True),91])92def test_classifier_matrix(status, body, category, retryable):93 c = classify("openai", status, body, {"retry-after": "3", "x-request-id": "req_x"})94 assert (c.category, c.retryable) == (category, retryable)95 assert c.retry_after == 3.0 and c.request_id == "req_x"96 assert 3.0 <= c.backoff(1) <= 3.397