{"record":{"id":"db20d89bff28c932","repo":"HKUDS/DeepTutor","slug":"embedding-provider-returned-http-response-status","errorCode":null,"errorMessage":"Embedding provider returned HTTP {response.status_code}","messagePattern":"Embedding provider returned HTTP (.+?)","errorType":"http","errorClass":"EmbeddingProviderError","httpStatus":400,"severity":"error","filePath":"deeptutor/services/embedding/adapters/openai_compatible.py","lineNumber":285,"sourceCode":"                            model=model,\n                            url=url,\n                            provider=\"openai_compat\",\n                        )\n\n                    if response.status_code >= 400:\n                        body_text = response.text\n                        if \"encoding_format\" not in payload and rejects_absent_encoding_format(\n                            response.status_code, body_text\n                        ):\n                            payload[\"encoding_format\"] = \"float\"\n                            logger.info(\n                                \"Gateway requires an explicit `encoding_format`; \"\n                                \"retrying once with 'float' (%s)\",\n                                url,\n                            )\n                            continue\n                        logger.error(f\"HTTP {response.status_code} from {url}: {body_text[:2000]}\")\n                        raise EmbeddingProviderError(\n                            f\"Embedding provider returned HTTP {response.status_code}\",\n                            status=response.status_code,\n                            body=body_text,\n                            model=model,\n                            url=url,\n                            provider=\"openai_compat\",\n                        )\n\n                    # A 2xx response with non-JSON body usually means the\n                    # endpoint/model pairing is wrong or a gateway routed us to\n                    # an HTML page. Surface that as structured diagnostics.\n                    try:\n                        data = response.json()\n                    except (json.JSONDecodeError, ValueError) as exc:\n                        body_text = response.text\n                        content_type = response.headers.get(\"content-type\", \"\")\n                        body_preview = body_text.strip()[:200] or \"<empty body>\"\n                        hint = \"\"","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/embedding/adapters/openai_compatible.py#L267-L303","documentation":"The embeddings endpoint returned an HTTP status >= 400 that is not one of the recoverable cases (the 429 key-rotation path and the encoding_format=400 auto-retry already ran). The full body is attached to the EmbeddingProviderError for diagnosis.","triggerScenarios":"400 for unsupported `dimensions` param on models that reject it; 401/403 for bad API key; 404 for wrong base_url or model; 500/502/503 gateway failures — after the automatic encoding_format retry did not match.","commonSituations":"Configuring dimensions on a non-OpenAI model whose gateway rejects the param; Azure deployments missing api-version; expired key; proxy routing to wrong backend.","solutions":["Read err.body — it contains the provider's error text (first 2000 chars logged as well)","401/403: fix the API key / Azure api-version; 404: fix base_url or model name; 400: check whether `dimensions` or other params must be disabled (set send_dimensions=False)","5xx: retry later or switch gateway endpoint","Reproduce with curl using the same payload to isolate adapter vs provider"],"exampleFix":"# before: gateway 400s on `dimensions`\nembedding_binding = {model: \"some-model\", dimensions: 1024}\n# after\nembedding_binding = {model: \"some-model\", dimensions: 1024, send_dimensions: false}","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"try:\n    resp = await adapter.embed(req)\nexcept EmbeddingProviderError as e:\n    if e.status and 400 <= e.status < 500:\n        log.error(\"config error: %s body=%s\", e, e.body)\n        raise ConfigurationError(e.body) from e\n    if e.status and e.status >= 500:\n        await asyncio.sleep(backoff); retry()\n    raise","preventionTips":["Set send_dimensions=False for models whose gateways reject `dimensions`","Smoke-test auth and model name with one request before batch indexing","Log err.body — it contains the provider's explanation"],"tags":["http-error","embeddings","provider-error","bad-request","auth"],"backgroundTag":"http-4xx-5xx-provider-error","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}