{"record":{"id":"d7cfb13000ae44ec","repo":"abi/screenshot-to-code","slug":"invalid-side-payload-error","errorCode":null,"errorMessage":"Invalid {side} payload: {error}","messagePattern":"Invalid (.+?) payload: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"backend/routes/evals.py","lineNumber":192,"sourceCode":"    formatted: str\n\n\ndef _load_openai_input_compare_payload(raw_json: str, side: str) -> object:\n    try:\n        payload = json.loads(raw_json)\n    except json.JSONDecodeError as error:\n        raise HTTPException(\n            status_code=400,\n            detail=(\n                f\"Invalid {side} JSON: {error.msg} \"\n                f\"(line {error.lineno}, column {error.colno})\"\n            ),\n        )\n\n    try:\n        compare_openai_inputs(payload, payload)\n    except ValueError as error:\n        raise HTTPException(status_code=400, detail=f\"Invalid {side} payload: {error}\")\n\n    return payload\n\n\n@router.post(\"/openai-input-compare\", response_model=OpenAIInputCompareResponse)\nasync def compare_openai_inputs_for_evals(\n    request: OpenAIInputCompareRequest,\n) -> OpenAIInputCompareResponse:\n    left_payload = _load_openai_input_compare_payload(request.left_json, \"left\")\n    right_payload = _load_openai_input_compare_payload(request.right_json, \"right\")\n    comparison = compare_openai_inputs(left_payload, right_payload)\n\n    difference = None\n    if comparison.difference is not None:\n        difference = OpenAIInputCompareDifferenceResponse(\n            item_index=comparison.difference.item_index,\n            path=comparison.difference.path,\n            left_summary=comparison.difference.left_summary,","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/abi/screenshot-to-code/blob/d026163f586dfa8c5c10d28c36edd59a9d3b0e88/backend/routes/evals.py#L174-L210","documentation":"400 raised by _load_openai_input_compare_payload in backend/routes/evals.py:192 when the JSON parses but compare_openai_inputs(payload, payload) raises ValueError — the decoded value is not a structurally valid OpenAI input payload (wrong shape/types for the comparison logic).","triggerScenarios":"POST /openai-input-compare where left_json/right_json is valid JSON but not an OpenAI input object — e.g. a bare string, number, array of wrong element types, or an object missing required fields.","commonSituations":"Comparing generic JSON that happens to be lying around; schema drift after an OpenAI API change; comparing the full request envelope instead of the inner input value.","solutions":["Read the detail: the ValueError message names the structural problem.","Ensure both sides are actual OpenAI 'input' payloads (message arrays / content parts) extracted from request bodies, not whole envelopes.","Add a client-side shape check for the expected array/object structure before sending."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function isOpenAiInputPayload(v: unknown): v is Array<{ role: string; content: unknown }> {\n  return Array.isArray(v) && v.every(\n    (m) => typeof m === 'object' && m !== null && typeof (m as any).role === 'string'\n  );\n}","tryCatchPattern":"if (res.status === 400 && detail.startsWith('Invalid left payload') || detail.startsWith('Invalid right payload')) {\n  // structural mismatch: show which side failed and the reason\n}","preventionTips":["Extract the inner 'input' field from logged requests, not the whole envelope.","Diff only payloads produced by the same tool version."],"tags":["http-400","json","validation","openai","fastapi"],"backgroundTag":null,"analyzedSha":"d026163f586dfa8c5c10d28c36edd59a9d3b0e88","analyzedAt":"2026-08-14T22:02:06.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}