floci-io/floci · error · CoercingSerializeException

Cannot serialize to JSON: {}

Error message

Cannot serialize to JSON: {}

What it means

The AWSJSON custom scalar failed during response serialization: a resolver returned a value for an AWSJSON field that Jackson could not write as JSON (CoercingSerializeException). AWSJSON fields accept a JSON string or an object; when the value is not already a string, Floci serializes it with a shared ObjectMapper, and any JsonProcessingException (e.g. a self-referencing object, or a exotic type the mapper cannot handle) surfaces as this error inside the GraphQL errors array rather than a transport 400.

Source

Thrown at src/main/java/io/github/hectorvent/floci/services/appsync/graphql/scalars/AppSyncScalars.java:38

import java.util.Base64;
import java.util.regex.Pattern;

public final class AppSyncScalars {

    private static final ObjectMapper SHARED_MAPPER = new ObjectMapper();

    public static final GraphQLScalarType AWSJSON = GraphQLScalarType.newScalar()
        .name("AWSJSON")
        .description("A JSON string")
        .coercing(new Coercing<String, String>() {
            @Override
            public String serialize(Object dataFetcherResult) {
                if (dataFetcherResult == null) return null;
                if (dataFetcherResult instanceof String s) return s;
                try {
                    return SHARED_MAPPER.writeValueAsString(dataFetcherResult);
                } catch (JsonProcessingException e) {
                    throw new CoercingSerializeException("Cannot serialize to JSON: " + e.getMessage());
                }
            }
            @Override
            public String parseValue(Object input) {
                String str = input.toString();
                try {
                    SHARED_MAPPER.readTree(str);
                } catch (Exception e) {
                    throw new CoercingParseValueException("Invalid JSON: " + str);
                }
                return str;
            }
            @Override
            public String parseLiteral(Object input) {
                if (!(input instanceof StringValue sv)) return null;
                return parseValue(sv.getValue());
            }
        })

View on GitHub (pinned to 62ff490619)

Solutions

  1. Have the resolver return either a pre-serialized JSON string or a plain DTO/Map tree without cycles for AWSJSON fields.
  2. Break object cycles (remove back-references or annotate them @JsonIgnore / JsonIdentityInfo).
  3. Convert driver-specific types (JSON-B, BSON documents) to plain Maps/lists before returning them.

Example fix

// before (cyclic map -> CoercingSerializeException)
Map<String,Object> a = new HashMap<>(), b = new HashMap<>();
a.put("b", b); b.put("a", a); // cycle
resolverResult = a;

// after
Map<String,Object> a = new HashMap<>(), b = new HashMap<>();
b.put("name", "child"); a.put("b", b); // no back-reference
resolverResult = a;
Defensive patterns

Strategy: validation

Validate before calling

// resolver-side: pre-serialize AWSJSON payloads yourself to bypass mapper pitfalls
String safeJson(Object v) {
    try { return new ObjectMapper().writeValueAsString(v); }
    catch (JsonProcessingException e) { throw new IllegalStateException("resolver payload not serializable: " + e.getMessage(), e); }
}
// return safeJson(result) for AWSJSON fields

Try / catch

// client side: AWSJSON errors arrive in the GraphQL 'errors' array with HTTP 200
const result = await graphqlRequest(...);
const ser = result.errors?.find(e => /Cannot serialize to JSON/.test(e.message));
if (ser) { /* log resolver payload shape; fix the mapping template to return a clean tree */ }

Prevention

When it happens

Trigger: A Lambda/data-source resolver mapping returns a cyclic object structure, a Java object with no serializable properties, or a type with no Jackson serializers on an AWSJSON field. The GraphQL response comes back with errors[] entry 'Cannot serialize to JSON: <Jackson message>'.

Common situations: Emulator resolver mappings building Maps that reference each other (cycles); returning raw driver/entity objects with lazy-loading proxies; Jackson modules not registered on the shared mapper for the returned type.

Related errors


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