{"record":{"id":"8d3b2cb63db7bcce","repo":"floci-io/floci","slug":"failed-to-serialize-v1-authorizer-event","errorCode":null,"errorMessage":"Failed to serialize v1 authorizer event","messagePattern":"Failed to serialize v1 authorizer event","errorType":"exception","errorClass":"RuntimeException","httpStatus":500,"severity":"error","filePath":"src/main/java/io/github/hectorvent/floci/services/apigateway/ApiGatewayExecuteController.java","lineNumber":1824,"sourceCode":"        putMultiValueQueryStringParameters(event, uriInfo);\n\n        event.putObject(\"pathParameters\");\n        event.putNull(\"stageVariables\");\n\n        // Request context\n        ObjectNode ctx = event.putObject(\"requestContext\");\n        ctx.put(\"accountId\", regionResolver.getAccountId());\n        ctx.put(\"apiId\", apiId);\n        ctx.put(\"httpMethod\", httpMethod);\n        ctx.put(\"path\", path);\n        ctx.put(\"resourcePath\", path);\n        ctx.put(\"stage\", stageName);\n        ctx.put(\"requestId\", UUID.randomUUID().toString());\n\n        try {\n            return objectMapper.writeValueAsString(event);\n        } catch (Exception e) {\n            throw new RuntimeException(\"Failed to serialize v1 authorizer event\", e);\n        }\n    }\n\n    /**\n     * Builds a REQUEST authorizer event in payload format version 2.0.\n     * Uses the newer HTTP API-native shape with routeArn, routeKey, rawPath, and requestContext.http.\n     */\n    private String buildRequestAuthorizerEventV2(String httpMethod, String path, String routeKey,\n                                                  String apiId, String stageName, String region,\n                                                  HttpHeaders headers, UriInfo uriInfo) {\n        ObjectNode event = objectMapper.createObjectNode();\n        event.put(\"version\", \"2.0\");\n        event.put(\"type\", \"REQUEST\");\n        event.put(\"routeArn\", buildMethodArn(region, apiId, stageName, httpMethod, path));\n        event.put(\"routeKey\", routeKey != null ? routeKey : \"$default\");\n        event.put(\"rawPath\", path);\n        event.put(\"rawQueryString\", uriInfo.getRequestUri().getRawQuery() != null\n                ? uriInfo.getRequestUri().getRawQuery() : \"\");","sourceCodeStart":1806,"sourceCodeEnd":1842,"githubUrl":"https://github.com/floci-io/floci/blob/62ff490619e7bd3554597c28c704081b4c15add5/src/main/java/io/github/hectorvent/floci/services/apigateway/ApiGatewayExecuteController.java#L1806-L1842","documentation":"While building a REQUEST authorizer event (payload v1) — requestContext with accountId, apiId, httpMethod, path, stage, requestId — ApiGatewayExecuteController serializes it with objectMapper.writeValueAsString(event) and wraps any failure in RuntimeException('Failed to serialize v1 authorizer event'). The tree only contains strings, so a failure indicates a broken ObjectMapper configuration in the emulator, not bad caller input.","triggerScenarios":"Invoking an execute-api route protected by a REQUEST (v1) Lambda authorizer while the ObjectMapper has a failing custom serializer/module, or a custom Floci build has Jackson version conflicts. Stock builds assemble the event from plain strings (UUID, stage name, account id), so serialization cannot fail under default configuration.","commonSituations":"Forked emulators that customize Jackson (custom modules, date serializers, property-naming strategies), native-image packaging missing reflection metadata for the serializer, or dependency shading merging Jackson classes. The resulting 500 surfaces only on authorized routes, so it can look stage- or auth-specific.","solutions":["Reproduce with the same route without the authorizer attached; if that works, the defect is in event serialization config, not auth logic.","Audit custom ObjectMapper producers/customizers in the build and remove them; Quarkus's default mapper handles ObjectNode fine.","Align Jackson versions with the Quarkus BOM (`./mvnw dependency:tree -Dincludes=com.fasterxml.jackson.*`).","For native images, register Jackson serializers for reflection and re-run the authorizer integration test.","Upstream: log the event node and rethrow as IllegalStateException so the 500 carries a diagnosable cause."],"exampleFix":"// before\ntry {\n    return objectMapper.writeValueAsString(event);\n} catch (Exception e) {\n    throw new RuntimeException(\"Failed to serialize v1 authorizer event\", e);\n}\n// after\ntry {\n    return objectMapper.writeValueAsString(event);\n} catch (JsonProcessingException e) {\n    LOG.errorf(e, \"V1 authorizer event serialization failed; event=%s\", event);\n    throw new IllegalStateException(\"Failed to serialize v1 authorizer event\", e);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Floci maintainer: narrow the catch and preserve the event for triage\ntry {\n    return objectMapper.writeValueAsString(event);\n} catch (JsonProcessingException e) {\n    LOG.errorf(e, \"V1 authorizer event serialization failed; event=%s\", event);\n    throw new IllegalStateException(\"Failed to serialize v1 authorizer event\", e);\n}","preventionTips":["Keep the emulator's Jackson configuration stock; custom serializers belong in the app under test, not the emulator.","Pin Jackson via the Quarkus BOM and re-check dependency:tree after any dependency addition.","Add a unit test that serializes v1 and v2 authorizer events end-to-end to catch mapper regressions.","Note the blast radius: only routes with REQUEST authorizers hit this path, so isolate before debugging auth logic."],"tags":["serialization","jackson","authorizer","lambda","server-error"],"backgroundTag":null,"analyzedSha":"62ff490619e7bd3554597c28c704081b4c15add5","analyzedAt":"2026-08-14T14:25:23.764Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}