floci-io/floci · error · RuntimeException

Failed to serialize proxy event

Error message

Failed to serialize proxy event

What it means

While building a Lambda proxy (payload v1/v2) event for an API Gateway execute-api invocation, ApiGatewayExecuteController serializes the assembled ObjectNode with objectMapper.writeValueAsString(event). Jackson declares JsonProcessingException, so the code wraps any failure in RuntimeException('Failed to serialize proxy event'). On ObjectNode trees with only String/boolean/null values this practically never fires; when it does it means the ObjectMapper is misconfigured (custom/failing serializers, blocked modules) rather than bad request data.

Source

Thrown at src/main/java/io/github/hectorvent/floci/services/apigateway/ApiGatewayExecuteController.java:765

                    if (value != null) {
                        authorizerNode.put(key, value.toString());
                    }
                });
            }
        }

        if (body != null && body.length > 0) {
            event.put("body", new String(body));
            event.put("isBase64Encoded", false);
        } else {
            event.putNull("body");
            event.put("isBase64Encoded", false);
        }

        try {
            return objectMapper.writeValueAsString(event);
        } catch (Exception e) {
            throw new RuntimeException("Failed to serialize proxy event", e);
        }
    }

    // Package-private for unit testing (see ApiGatewayExecuteControllerTest).
    void putSingleValueHeaders(ObjectNode event, HttpHeaders headers) {
        ObjectNode headersNode = event.putObject("headers");
        headers.getRequestHeaders().forEach((name, values) -> {
            // AWS collapses duplicate request headers to the LAST value in the single-value `headers`
            // map (multiValueHeaders keeps every value). Taking the first value diverged from AWS.
            if (!values.isEmpty()) {
                headersNode.put(name, values.get(values.size() - 1));
            }
        });
    }

    void putMultiValueHeaders(ObjectNode event, HttpHeaders headers) {
        ObjectNode mvHeaders = event.putObject("multiValueHeaders");
        headers.getRequestHeaders().forEach((name, values) -> {

View on GitHub (pinned to 62ff490619)

Solutions

  1. Treat this as a server defect, not a client error: it maps to HTTP 500, so fix the emulator configuration, not the request.
  2. Check for a custom ObjectMapper binding or added Jackson module in your build (Quarkus CDI producer, ObjectMapper customizer) and remove/fix it.
  3. Verify Jackson dependency versions with `./mvnw dependency:tree -Dincludes=com.fasterxml.jackson.*` and align them with the Quarkus BOM.
  4. For native-image builds, add the affected serializer classes to reflection registers and re-test.
  5. As an upstream fix, wrap JsonProcessingException and log the offending event node so the failure is diagnosable.

Example fix

// before
try {
    return objectMapper.writeValueAsString(event);
} catch (Exception e) {
    throw new RuntimeException("Failed to serialize proxy event", e);
}
// after: keep the 500 but make it diagnosable
try {
    return objectMapper.writeValueAsString(event);
} catch (JsonProcessingException e) {
    LOG.errorf(e, "Proxy event serialization failed; event=%s", event);
    throw new IllegalStateException("Failed to serialize proxy event", e);
}
Defensive patterns

Strategy: try-catch

Try / catch

// Floci maintainer: fail loudly and log the node so the config defect is visible
try {
    return objectMapper.writeValueAsString(event);
} catch (JsonProcessingException e) {
    LOG.errorf(e, "Proxy event serialization failed; event=%s", event);
    throw new IllegalStateException("Failed to serialize proxy event", e);
}

Prevention

When it happens

Trigger: Invoking an execute-api endpoint backed by a Lambda proxy integration (POST/GET on the stage path) while the injected ObjectMapper has a registered module or custom serializer that throws for the node types used (body, isBase64Encoded, headers). Also possible with a corrupted Jackson runtime after dependency shading or version conflicts in a custom Floci build.

Common situations: Custom Floci forks that replace/annotate the ObjectMapper (e.g. a module that serializes dates oddly), native-image builds where a Jackson serializer lacks reflection metadata, or Jackson version clashes introduced by an added dependency. For stock Floci the path is effectively unreachable.

Related errors


AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14). Data as JSON: /api/errors/4dbf8f16581eb84e. Report an issue: GitHub.