{"record":{"id":"a8dbdfb21a8ef21d","repo":"apache/flink","slug":"could-not-copy-object-by-serializing-deserializing","errorCode":null,"errorMessage":"Could not copy object by serializing/deserializing it.","messagePattern":"Could not copy object by serializing/deserializing it\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/KryoUtils.java","lineNumber":56,"sourceCode":"     * record from is copied by serializing it into a byte buffer and deserializing it from there.\n     *\n     * @param from Element to copy\n     * @param kryo Kryo instance to use\n     * @param serializer TypeSerializer which is used in case of a Kryo failure\n     * @param <T> Type of the element to be copied\n     * @return Copied element\n     */\n    public static <T> T copy(T from, Kryo kryo, TypeSerializer<T> serializer) {\n        try {\n            return kryo.copy(from);\n        } catch (KryoException ke) {\n            // Kryo could not copy the object --> try to serialize/deserialize the object\n            try {\n                byte[] byteArray = InstantiationUtil.serializeToByteArray(serializer, from);\n\n                return InstantiationUtil.deserializeFromByteArray(serializer, byteArray);\n            } catch (IOException ioe) {\n                throw new RuntimeException(\n                        \"Could not copy object by serializing/deserializing\" + \" it.\", ioe);\n            }\n        }\n    }\n\n    /**\n     * Tries to copy the given record from using the provided Kryo instance. If this fails, then the\n     * record from is copied by serializing it into a byte buffer and deserializing it from there.\n     *\n     * @param from Element to copy\n     * @param reuse Reuse element for the deserialization\n     * @param kryo Kryo instance to use\n     * @param serializer TypeSerializer which is used in case of a Kryo failure\n     * @param <T> Type of the element to be copied\n     * @return Copied element\n     */\n    public static <T> T copy(T from, T reuse, Kryo kryo, TypeSerializer<T> serializer) {\n        try {","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/KryoUtils.java#L38-L74","documentation":"KryoUtils.copy(from, kryo, serializer) first tries kryo.copy(from); if Kryo cannot copy (KryoException), it falls back to serialize/deserialize via the provided TypeSerializer. This error means both paths failed: the IOException from InstantiationUtil.serializeToByteArray/deserializeFromByteArray is wrapped in this RuntimeException.","triggerScenarios":"Calling KryoUtils.copy during operator chaining, iteractive/feedback streams, or session windowing state copies; Kryo copy fails (no accessible constructor / unregistered class), then serialization fails because the object graph contains a non-serializable field or the serializer snapshot is incompatible.","commonSituations":"A custom class used as a key or in managed state has a non-serializable field (e.g. an open connection, Thread, or lambda); Kryo registration ids changed between job submissions while restoring state; a custom TypeSerializer that throws on serialize; deep object graphs exceeding Kryo's max depth.","solutions":["Read the wrapped IOException - it identifies which field/object failed to serialize","Make every field of the copied type Serializable or Kryo-serializable, or mark non-serializable fields transient and reinitialize them","Give the class a public no-arg constructor so kryo.copy() succeeds and the fallback is never needed","Register the class with a stable registration id in the Kryo registrar instead of relying on class-name mode","If state restore is involved, ensure the serializer's snapshot version matches the data being read"],"exampleFix":"// before\nclass SessionState {\n    Connection conn; // not serializable\n}\n\n// after\nclass SessionState implements Serializable {\n    transient Connection conn; // re-opened in open()\n    String sessionId;\n}","handlingStrategy":"try-catch","validationCode":"// Before copying, verify the type can round-trip through the serializer\ntry {\n    InstantiationUtil.serializeToByteArray(serializer, sampleElement);\n} catch (IOException e) {\n    throw new IllegalStateException(\"Element is not serializable: \" + e, e);\n}","typeGuard":"static boolean isKryoCopyable(Class<?> c) {\n    try {\n        c.getDeclaredConstructor().setAccessible(true);\n        return true;\n    } catch (ReflectiveOperationException e) {\n        return false;\n    }\n}","tryCatchPattern":"try {\n    T copy = KryoUtils.copy(from, kryo, serializer);\n} catch (RuntimeException e) {\n    // both kryo.copy and serialize/deserialize failed\n    throw new IllegalStateException(\"Cannot copy element of \" + from.getClass(), e.getCause());\n}","preventionTips":["Give classes used in state a public no-arg constructor so kryo.copy() succeeds","Keep all fields Serializable or transient+reinitialized","Register custom types with stable Kryo registration ids"],"tags":["kryo","serialization","copy","state"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}