flowable/flowable-engine · error · FlowableException

Couldn't serialize value

Error message

Couldn't serialize value '${value}' in variable '${name}'

What it means

Flowable's SerializableType serializes a variable value to bytes via Java ObjectOutputStream before persisting it. This FlowableException wraps any exception thrown during writeObject (NotSerializableException, IOException, etc.), naming the value and the variable. It means the value stored in the variable cannot be Java-serialized.

Solutions

  1. Make the variable's class (and every object it references transitively) implement java.io.Serializable
  2. Store only small, serializable data (ids, JSON strings) in variables instead of live objects; re-fetch objects in delegates
  3. Inspect the cause: NotSerializableException names the first offending class — fix that class or mark the field transient
  4. If the object is huge or non-serializable by design, keep it out of the variable scope (pass via external store and put only the key in the variable)

Example fix

// before
runtimeService.setVariable(executionId, "customer", new CustomerService());
// after
runtimeService.setVariable(executionId, "customerId", customer.getId());
Defensive patterns

Strategy: try-catch

Validate before calling

private static boolean isSerializable(Object o) {
    if (o instanceof Serializable) return true;
    try { new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(o); return true; }
    catch (NotSerializableException e) { return false; }
    catch (IOException e) { return false; }
}

Type guard

if (!(value instanceof java.io.Serializable)) {
    throw new IllegalArgumentException("Variable value must implement Serializable: " + value.getClass());
}

Try / catch

try {
    runtimeService.setVariable(executionId, name, value);
} catch (FlowableException e) {
    if (e.getCause() instanceof NotSerializableException) {
        log.error("Variable {} value not serializable: {}", name, e.getCause().getMessage());
    }
    throw e;
}

Prevention

When it happens

Trigger: Setting a process/execution/task variable (or a transient variable) whose runtime type does not implement java.io.Serializable, or whose fields reference non-serializable objects; serialization stream corruption or a custom writeObject throwing; createObjectOutputStream failing.

Common situations: Putting a Spring service bean, an InputStream/Connection, a lambda capturing a non-serializable context, or a Mockito mock into a process variable; an object graph that gained a non-serializable field after a dependency upgrade.

Understand the failure class

Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/90270a4cc89f6a24. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-variable-service/src/main/java/org/flowable/variable/service/impl/types/SerializableType.java:146

            if (!Arrays.equals(refreshedOriginalBytes, bytes)) {
                variableInstanceEntity.setBytes(bytes);
                valueChanged = true;
            }
        }
        return valueChanged;
    }

    public byte[] serialize(Object value, ValueFields valueFields) {
        if (value == null) {
            return null;
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = null;
        try {
            oos = createObjectOutputStream(baos);
            oos.writeObject(value);
        } catch (Exception e) {
            throw new FlowableException("Couldn't serialize value '" + value + "' in variable '" + valueFields.getName() + "'", e);
        } finally {
            IoUtil.closeSilently(oos);
        }
        return baos.toByteArray();
    }

    public Object deserialize(byte[] bytes, ValueFields valueFields) {
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        try {
            ObjectInputStream ois = createObjectInputStream(bais);
            Object deserializedObject = ois.readObject();

            return deserializedObject;
        } catch (Exception e) {
            throw new FlowableException("Couldn't deserialize object in variable '" + valueFields.getName() + "'", e);
        } finally {
            IoUtil.closeSilently(bais);
        }

View on GitHub (pinned to d6d39ce1c6)