flowable/flowable-engine · error · ActivitiException

Unexpected exception when serializing JPA id's

Error message

Unexpected exception when serializing JPA id's

What it means

Thrown by JPAEntityListVariableType.serializeIds() when Java object serialization of the String[] of entity IDs fails with IOException. The engine serializes the collected entity primary keys to bytes for the variable table; any stream/serialization failure is wrapped in ActivitiException.

Source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/variable/JPAEntityListVariableType.java:154

            return result;
        }
        return null;
    }

    /**
     * @return a bytearray containing all ID's in the given string serialized as an array.
     */
    protected byte[] serializeIds(List<String> ids) {
        try {
            String[] toStore = ids.toArray(new String[]{});
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(baos);

            out.writeObject(toStore);
            return baos.toByteArray();
        } catch (IOException ioe) {
            throw new ActivitiException("Unexpected exception when serializing JPA id's", ioe);
        }
    }

    protected String[] deserializeIds(byte[] bytes) {
        try {
            ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
            ObjectInputStream in = new ObjectInputStream(bais);

            Object read = in.readObject();
            if (!(read instanceof String[])) {
                throw new ActivitiIllegalArgumentException("Deserialized value is not an array of ID's: " + read);
            }

            return (String[]) read;
        } catch (IOException ioe) {
            throw new ActivitiException("Unexpected exception when deserializing JPA id's", ioe);
        } catch (ClassNotFoundException e) {
            throw new ActivitiException("Unexpected exception when deserializing JPA id's", e);

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Inspect the chained IOException for the actual serialization failure
  2. Ensure only String[] of IDs is passed to serialization (do not store raw entities in the id array)
  3. Confirm element classes are Serializable if the stored structure was customized
  4. Avoid modifying the serialization format between engine versions without variable migration

Example fix

// before
out.writeObject(rawEntities); // non-serializable entities
// after
out.writeString(idStrings); // String[] of entity primary keys
Defensive patterns

Strategy: try-catch

Validate before calling

// ids are Strings by design; verify before serialization
boolean allStrings = java.util.Arrays.stream(ids).allMatch(Objects::nonNull);

Type guard

boolean isSerializableStringArray(Object ids) {
    return ids instanceof String[] && java.util.Arrays.stream((String[]) ids).allMatch(Objects::nonNull);
}

Try / catch

try {
    runtimeService.setVariable(executionId, "orders", orderList);
} catch (ActivitiException e) {
    if (e.getCause() instanceof IOException) {
        logger.error("JPA id serialization failed", e.getCause());
    }
    throw e;
}

Prevention

When it happens

Trigger: IOException on ObjectOutputStream.writeObject of the String[] ids (e.g. underlying ByteArrayOutputStream issues are rare; usually caused by custom objects in a overridden toStore array or IO infrastructure failure).

Common situations: Custom subclasses overriding id extraction so the array contains non-serializable elements; environment-level IO problems; JVM-level serialization incompatibility after changing the stored type.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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