flowable/flowable-engine · error · ActivitiIllegalArgumentException

Deserialized value is not an array of ID's: ${read}

Error message

Deserialized value is not an array of ID's: ${read}

What it means

Thrown by JPAEntityListVariableType.deserializeIds() when the deserialized object read from the variable's byte column is not a String[]. The type validates the shape of the stored payload before casting, raising ActivitiIllegalArgumentException identifying the unexpected object.

Source

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

            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. Verify the variable was created by JPAEntityListVariableType (check TYPE_ column in ACT_GE_BYTEARRAY / variable table)
  2. Delete and re-create the corrupted variable with correct entity list data
  3. Check for engine version mismatch between write and read nodes in a cluster
  4. Write a data migration for variables stored in the old format

Example fix

// before
// variable bytes contain ArrayList, list type expects String[]
Object read = in.readObject(); // ArrayList -> throws
// after
if (read instanceof String[]) {
    return (String[]) read;
}
// or migrate: rewrite variable as proper JPA entity list
Defensive patterns

Strategy: validation

Validate before calling

// detect legacy/mismatched variable payloads before reading
String type = variable.getType().getTypeName();
if (!"jpa-entity-list".equals(type)) {
    throw new IllegalStateException("Variable " + variable.getName() + " is not a jpa-entity-list: " + type);
}

Type guard

Object read = in.readObject();
if (read instanceof String[]) {
    String[] ids = (String[]) read;
}

Try / catch

try {
    Object orders = runtimeService.getVariable(executionId, "orders");
} catch (ActivitiIllegalArgumentException e) {
    if (e.getMessage().startsWith("Deserialized value is not an array of ID's")) {
        // migrate or re-create the variable
    }
    throw e;
}

Prevention

When it happens

Trigger: Reading a JPA entity list variable whose byte payload was written by a different variable type or an older engine format; corrupted/hand-edited ACT_GE_BYTEARRAY content; a custom serializer stored a different object type.

Common situations: Engine upgrade where the variable storage format changed; variables written by custom code directly into the byte array table; mixing single-entity and list variable types on the same variable name.

Related errors


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