{"record":{"id":"a70fba7d2e451b9f","repo":"floci-io/floci","slug":"badrequestexception-a70fba","errorCode":"BadRequestException","errorMessage":"e.getMessage()","messagePattern":"e\\.getMessage\\(\\)","errorType":"http","errorClass":"AwsException","httpStatus":400,"severity":"error","filePath":"src/main/java/io/github/hectorvent/floci/services/apigateway/ApiGatewayController.java","lineNumber":105,"sourceCode":"        return Response.ok(toMethodResponseNode(service.getMethodResponse(region, apiId, resourceId, httpMethod, statusCode)).toString()).type(MediaType.APPLICATION_JSON).build();\n    }\n\n    @PUT\n    @Path(\"/restapis/{apiId}/resources/{resourceId}/methods/{httpMethod}/responses/{statusCode}\")\n    public Response putMethodResponse(@Context HttpHeaders headers,\n                                      @PathParam(\"apiId\") String apiId,\n                                      @PathParam(\"resourceId\") String resourceId,\n                                      @PathParam(\"httpMethod\") String httpMethod,\n                                      @PathParam(\"statusCode\") String statusCode,\n                                      String body) {\n        String region = regionResolver.resolveRegion(headers);\n        try {\n            @SuppressWarnings(\"unchecked\")\n            Map<String, Object> request = objectMapper.readValue(body, Map.class);\n            MethodResponse resp = service.putMethodResponse(region, apiId, resourceId, httpMethod, statusCode, request);\n            return Response.status(201).entity(toMethodResponseNode(resp).toString()).type(MediaType.APPLICATION_JSON).build();\n        } catch (IOException e) {\n            throw new AwsException(\"BadRequestException\", e.getMessage(), 400);\n        }\n    }\n\n    @GET\n    @Path(\"/restapis/{apiId}/resources/{resourceId}/methods/{httpMethod}/integration/responses/{statusCode}\")\n    public Response getIntegrationResponse(@Context HttpHeaders headers,\n                                           @PathParam(\"apiId\") String apiId,\n                                           @PathParam(\"resourceId\") String resourceId,\n                                           @PathParam(\"httpMethod\") String httpMethod,\n                                           @PathParam(\"statusCode\") String statusCode) {\n        String region = regionResolver.resolveRegion(headers);\n        return Response.ok(toIntegrationResponseNode(service.getIntegrationResponse(region, apiId, resourceId, httpMethod, statusCode)).toString()).type(MediaType.APPLICATION_JSON).build();\n    }\n\n    @PUT\n    @Path(\"/restapis/{apiId}/resources/{resourceId}/methods/{httpMethod}/integration/responses/{statusCode}\")\n    public Response putIntegrationResponse(@Context HttpHeaders headers,\n                                           @PathParam(\"apiId\") String apiId,","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/floci-io/floci/blob/62ff490619e7bd3554597c28c704081b4c15add5/src/main/java/io/github/hectorvent/floci/services/apigateway/ApiGatewayController.java#L87-L123","documentation":"PutMethodResponse in the API Gateway emulator parses the raw request body with Jackson; any IOException from objectMapper.readValue is rethrown as a 400 BadRequestException carrying Jackson's message. Malformed JSON, a non-object payload (array/string), or unreadable content all land here.","triggerScenarios":"PUT /restapis/{apiId}/resources/{resourceId}/methods/{httpMethod}/responses/{statusCode} with a body that is not a valid JSON object — trailing commas, single quotes, empty string, or a JSON array.","commonSituations":"Hand-rolled curl requests with shell-quoting mistakes; SDK clients that send an empty entity on error paths; proxies or transforms that mangle the JSON body in transit.","solutions":["Validate the body is a JSON object before sending (jq . <<< body or a client-side parse)","Send exactly the expected shape: {\"selectionPattern\": \"...\", \"responseTemplates\": {...}}"],"exampleFix":"// before\nString body = \"[\\\"selectionPattern\\\"]\"; // JSON array\n// after\nString body = \"{\\\"selectionPattern\\\": \\\"2\\\\d{2}\\\"}\";","handlingStrategy":"validation","validationCode":"ObjectMapper om = new ObjectMapper();\nJsonNode n = om.readTree(body);\nif (!n.isObject()) throw new IllegalArgumentException(\"Body must be a JSON object\");","typeGuard":"boolean isValidMethodResponseBody(String body, ObjectMapper om) throws Exception {\n    JsonNode n = om.readTree(body);\n    return n.isObject();\n}","tryCatchPattern":"try {\n    apigw.putMethodResponse(req);\n} catch (BadRequestException e) {\n    // Jackson message indicates the exact offset; re-check the serialized body\n    log.error(\"Rejected body: {}\", rawBody);\n    throw e;\n}","preventionTips":["Always set Content-Type: application/json on REST calls to the emulator","Prefer the AWS SDK over hand-rolled HTTP for management-plane calls"],"tags":["apigateway","json","put-method-response","bad-request"],"backgroundTag":null,"analyzedSha":"62ff490619e7bd3554597c28c704081b4c15add5","analyzedAt":"2026-08-14T14:25:23.764Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}