{"record":{"id":"1b2b85a56aecc6ca","repo":"floci-io/floci","slug":"cannot-serialize-to-json","errorCode":null,"errorMessage":"Cannot serialize to JSON: {}","messagePattern":"Cannot serialize to JSON: (.+?)","errorType":"validation","errorClass":"CoercingSerializeException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/github/hectorvent/floci/services/appsync/graphql/scalars/AppSyncScalars.java","lineNumber":38,"sourceCode":"import java.util.Base64;\nimport java.util.regex.Pattern;\n\npublic final class AppSyncScalars {\n\n    private static final ObjectMapper SHARED_MAPPER = new ObjectMapper();\n\n    public static final GraphQLScalarType AWSJSON = GraphQLScalarType.newScalar()\n        .name(\"AWSJSON\")\n        .description(\"A JSON string\")\n        .coercing(new Coercing<String, String>() {\n            @Override\n            public String serialize(Object dataFetcherResult) {\n                if (dataFetcherResult == null) return null;\n                if (dataFetcherResult instanceof String s) return s;\n                try {\n                    return SHARED_MAPPER.writeValueAsString(dataFetcherResult);\n                } catch (JsonProcessingException e) {\n                    throw new CoercingSerializeException(\"Cannot serialize to JSON: \" + e.getMessage());\n                }\n            }\n            @Override\n            public String parseValue(Object input) {\n                String str = input.toString();\n                try {\n                    SHARED_MAPPER.readTree(str);\n                } catch (Exception e) {\n                    throw new CoercingParseValueException(\"Invalid JSON: \" + str);\n                }\n                return str;\n            }\n            @Override\n            public String parseLiteral(Object input) {\n                if (!(input instanceof StringValue sv)) return null;\n                return parseValue(sv.getValue());\n            }\n        })","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/floci-io/floci/blob/62ff490619e7bd3554597c28c704081b4c15add5/src/main/java/io/github/hectorvent/floci/services/appsync/graphql/scalars/AppSyncScalars.java#L20-L56","documentation":"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.","triggerScenarios":"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>'.","commonSituations":"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.","solutions":["Have the resolver return either a pre-serialized JSON string or a plain DTO/Map tree without cycles for AWSJSON fields.","Break object cycles (remove back-references or annotate them @JsonIgnore / JsonIdentityInfo).","Convert driver-specific types (JSON-B, BSON documents) to plain Maps/lists before returning them."],"exampleFix":"// before (cyclic map -> CoercingSerializeException)\nMap<String,Object> a = new HashMap<>(), b = new HashMap<>();\na.put(\"b\", b); b.put(\"a\", a); // cycle\nresolverResult = a;\n\n// after\nMap<String,Object> a = new HashMap<>(), b = new HashMap<>();\nb.put(\"name\", \"child\"); a.put(\"b\", b); // no back-reference\nresolverResult = a;","handlingStrategy":"validation","validationCode":"// resolver-side: pre-serialize AWSJSON payloads yourself to bypass mapper pitfalls\nString safeJson(Object v) {\n    try { return new ObjectMapper().writeValueAsString(v); }\n    catch (JsonProcessingException e) { throw new IllegalStateException(\"resolver payload not serializable: \" + e.getMessage(), e); }\n}\n// return safeJson(result) for AWSJSON fields","typeGuard":null,"tryCatchPattern":"// client side: AWSJSON errors arrive in the GraphQL 'errors' array with HTTP 200\nconst result = await graphqlRequest(...);\nconst ser = result.errors?.find(e => /Cannot serialize to JSON/.test(e.message));\nif (ser) { /* log resolver payload shape; fix the mapping template to return a clean tree */ }","preventionTips":["Return plain Maps/lists (no cycles, no ORM proxies) from resolver mappings for AWSJSON fields.","Pre-serialize AWSJSON values to strings in the mapping template so server-side coercion is trivial.","Integration-test every AWSJSON field with representative payloads before shipping resolvers."],"tags":["appsync","graphql","scalars","awsjson","serialization"],"backgroundTag":null,"analyzedSha":"62ff490619e7bd3554597c28c704081b4c15add5","analyzedAt":"2026-08-14T14:25:23.764Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}