{"record":{"id":"e4092e08ac7c700f","repo":"floci-io/floci","slug":"malformedhttprequestexception","errorCode":"MalformedHttpRequestException","errorMessage":"Request body is empty.","messagePattern":"Request body is empty\\.","errorType":"http","errorClass":"AppSyncTransportException","httpStatus":400,"severity":"error","filePath":"src/main/java/io/github/hectorvent/floci/services/appsync/graphql/AppSyncExecutionController.java","lineNumber":115,"sourceCode":"        }\n    }\n\n    private boolean isAcceptedContentType(HttpHeaders headers) {\n        String contentType = headers.getHeaderString(HttpHeaders.CONTENT_TYPE);\n        if (contentType == null || contentType.isBlank()) {\n            return false;\n        }\n        String normalized = contentType.toLowerCase(Locale.ROOT).trim();\n        int semicolon = normalized.indexOf(';');\n        if (semicolon >= 0) {\n            normalized = normalized.substring(0, semicolon).trim();\n        }\n        return \"application/json\".equals(normalized) || \"application/graphql\".equals(normalized);\n    }\n\n    private ParsedRequest parseBody(String body) {\n        if (body == null || body.isBlank()) {\n            throw new AppSyncTransportException(400, \"MalformedHttpRequestException\",\n                    AppSyncErrorFormatter.MSG_EMPTY_BODY);\n        }\n\n        JsonNode root;\n        try {\n            root = objectMapper.readTree(body);\n        } catch (JsonProcessingException e) {\n            throw new AppSyncTransportException(400, \"MalformedHttpRequestException\",\n                    AppSyncErrorFormatter.MSG_UNABLE_TO_PARSE);\n        }\n\n        if (root == null || root.isNull() || root.isArray() || !root.isObject()) {\n            throw new AppSyncTransportException(400, \"MalformedHttpRequestException\",\n                    AppSyncErrorFormatter.MSG_UNABLE_TO_PARSE);\n        }\n        if (root.isEmpty()) {\n            throw new AppSyncTransportException(400, \"MalformedHttpRequestException\",\n                    AppSyncErrorFormatter.MSG_UNABLE_TO_PARSE);","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/floci-io/floci/blob/62ff490619e7bd3554597c28c704081b4c15add5/src/main/java/io/github/hectorvent/floci/services/appsync/graphql/AppSyncExecutionController.java#L97-L133","documentation":"The GraphQL-over-HTTP execution endpoint (POST /graphql/{apiId}) received a request whose body was null or blank (empty, or only whitespace). Floci's AppSyncExecutionController.parseBody rejects this before any JSON or GraphQL parsing with HTTP 400 and error type MalformedHttpRequestException, matching real AppSync behavior for empty request bodies.","triggerScenarios":"POSTing to the GraphQL endpoint with Content-Length 0, a body of only spaces/newlines, or letting an HTTP client send no body at all (e.g. forgetting to attach the JSON payload, or a GET-style invocation of a POST endpoint). Sending an empty string as the body field also triggers it.","commonSituations":"Missing .body(...) in fetch/axios calls; proxy or load balancer stripping request bodies; curl invocations where the --data flag was omitted; SDK code paths that build the request conditionally and skip the payload.","solutions":["Ensure the POST body is a non-empty JSON object like {\"query\": \"{ __typename }\"} and that your HTTP client actually sends it.","Check intermediate proxies (dev proxy, nginx, API gateway) are not dropping or buffering the request body.","Add a client-side assertion that the serialized body is non-blank before dispatching."],"exampleFix":"// before\nfetch(url, { method: 'POST', headers }); // no body sent -> 400\n\n// after\nfetch(url, { method: 'POST', headers, body: JSON.stringify({ query: '{ __typename }' }) });","handlingStrategy":"validation","validationCode":"function assertBody(body) {\n  if (body == null || body.trim() === '') throw new Error('GraphQL request body is empty');\n  return body;\n}\nfetch(url, { method: 'POST', body: assertBody(JSON.stringify({ query })) });","typeGuard":null,"tryCatchPattern":"const resp = await fetch(url, req);\nif (resp.status === 400) {\n  const err = await resp.json();\n  if (/empty/i.test(err.errors?.[0]?.message ?? '')) throw new Error('bug: request body not sent — check client/proxy');\n}","preventionTips":["Always set the body option explicitly in HTTP clients.","Integration-test the request path with a body-capturing mock to catch proxy stripping.","Watch for MalformedHttpRequestException with the empty-body message in CI — it indicates client wiring bugs, not server issues."],"tags":["appsync","graphql","http","request-body"],"backgroundTag":null,"analyzedSha":"62ff490619e7bd3554597c28c704081b4c15add5","analyzedAt":"2026-08-14T14:25:23.764Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}