{"record":{"id":"0da49db34cc1a55a","repo":"infiniflow/ragflow","slug":"str-object-has-no-attribute-get","errorCode":null,"errorMessage":"'str' object has no attribute 'get'","messagePattern":"'str' object has no attribute 'get'","errorType":"validation","errorClass":"AttributeError","httpStatus":null,"severity":"warning","filePath":"api/utils/api_utils.py","lineNumber":79,"sourceCode":"async def _coerce_request_data() -> dict:\n    \"\"\"Fetch JSON body with sane defaults; fallback to form data.\"\"\"\n    if hasattr(request, \"_cached_payload\"):\n        return request._cached_payload\n    payload: Any = None\n\n    body_bytes = await request.get_data()\n    has_body = bool(body_bytes)\n    content_type = (request.content_type or \"\").lower()\n    is_json = content_type.startswith(\"application/json\")\n\n    if not has_body:\n        payload = {}\n    elif is_json:\n        payload = await request.get_json(force=False, silent=False)\n        if isinstance(payload, dict):\n            payload = payload or {}\n        elif isinstance(payload, str):\n            raise AttributeError(\"'str' object has no attribute 'get'\")\n        else:\n            raise TypeError(\"JSON payload must be an object.\")\n    else:\n        form = await request.form\n        payload = form.to_dict() if form else None\n        if payload is None:\n            raise TypeError(\"Request body is not a valid form payload.\")\n\n    request._cached_payload = payload\n    return payload\n\n\nasync def get_request_json():\n    return await _coerce_request_data()\n\n\ndef serialize_for_json(obj):\n    \"\"\"","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/api/utils/api_utils.py#L61-L97","documentation":"Raised by _coerce_request_data in api_utils when a JSON body parses to a bare string (e.g. the literal body \"\\\"hello\\\"\" or a quoted token). RAGFlow request handlers expect a JSON object mapping to kwargs; scalar JSON values are rejected with this AttributeError before reaching the handler.","triggerScenarios":"POSTing with Content-Type: application/json a body that is a JSON string rather than an object: '\"text\"', a bare JWT, or a double-encoded payload ('\\\"{\\\\\\\"a\\\\\\\":1}\\\"').","commonSituations":"Clients double-serializing JSON (json.dumps twice); pasting a raw token as the body; curl -d '\"hello\"' without realizing the endpoint needs an object.","solutions":["Send a JSON object as the body: {\"key\": \"value\"} with Content-Type: application/json.","Remove double serialization in the client: call json.dumps (or the requests json= parameter) exactly once.","Validate the payload shape client-side before sending."],"exampleFix":"# before\nrequests.post(url, data=json.dumps(json.dumps(payload)))  # double-encoded string\n\n# after\nrequests.post(url, json=payload)  # sends an object once","handlingStrategy":"type-guard","validationCode":"body = payload if isinstance(payload, dict) else {'value': payload}  # client side: always send an object","typeGuard":"def is_json_object_body(payload) -> bool:\n    return isinstance(payload, dict)","tryCatchPattern":"try:\n    data = await get_request_json()\nexcept AttributeError:\n    return json_error_response('JSON body must be an object, not a string', 400)","preventionTips":["Serialize JSON exactly once; prefer requests' json= parameter.","Never send bare quoted strings or tokens as a JSON body."],"tags":["validation","json","http","request-body","api"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}