floci-io/floci · error · AppSyncTransportException
MalformedHttpRequestException
MalformedHttpRequestException
Error message
Request body is empty.
What it means
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.
Source
Thrown at src/main/java/io/github/hectorvent/floci/services/appsync/graphql/AppSyncExecutionController.java:115
}
}
private boolean isAcceptedContentType(HttpHeaders headers) {
String contentType = headers.getHeaderString(HttpHeaders.CONTENT_TYPE);
if (contentType == null || contentType.isBlank()) {
return false;
}
String normalized = contentType.toLowerCase(Locale.ROOT).trim();
int semicolon = normalized.indexOf(';');
if (semicolon >= 0) {
normalized = normalized.substring(0, semicolon).trim();
}
return "application/json".equals(normalized) || "application/graphql".equals(normalized);
}
private ParsedRequest parseBody(String body) {
if (body == null || body.isBlank()) {
throw new AppSyncTransportException(400, "MalformedHttpRequestException",
AppSyncErrorFormatter.MSG_EMPTY_BODY);
}
JsonNode root;
try {
root = objectMapper.readTree(body);
} catch (JsonProcessingException e) {
throw new AppSyncTransportException(400, "MalformedHttpRequestException",
AppSyncErrorFormatter.MSG_UNABLE_TO_PARSE);
}
if (root == null || root.isNull() || root.isArray() || !root.isObject()) {
throw new AppSyncTransportException(400, "MalformedHttpRequestException",
AppSyncErrorFormatter.MSG_UNABLE_TO_PARSE);
}
if (root.isEmpty()) {
throw new AppSyncTransportException(400, "MalformedHttpRequestException",
AppSyncErrorFormatter.MSG_UNABLE_TO_PARSE);View on GitHub (pinned to 62ff490619)
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.
Example fix
// before
fetch(url, { method: 'POST', headers }); // no body sent -> 400
// after
fetch(url, { method: 'POST', headers, body: JSON.stringify({ query: '{ __typename }' }) }); Defensive patterns
Strategy: validation
Validate before calling
function assertBody(body) {
if (body == null || body.trim() === '') throw new Error('GraphQL request body is empty');
return body;
}
fetch(url, { method: 'POST', body: assertBody(JSON.stringify({ query })) }); Try / catch
const resp = await fetch(url, req);
if (resp.status === 400) {
const err = await resp.json();
if (/empty/i.test(err.errors?.[0]?.message ?? '')) throw new Error('bug: request body not sent — check client/proxy');
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- BadRequestException
- BadRequestException
- Cannot serialize to JSON: {}
- Invalid JSON: {}
- Invalid AWSDateTime: {}
AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14).
Data as JSON: /api/errors/e4092e08ac7c700f.
Report an issue: GitHub.