flowable/flowable-engine · error · ActivitiIllegalArgumentException

Value of primary key for JPA-Entity cannot be null

Error message

Value of primary key for JPA-Entity cannot be null

What it means

Thrown by JPAEntityMappings.getIdString when the primary key value of a JPA-managed entity variable is null. The engine needs the entity's PK to persist the variable reference, so a null PK is rejected as an illegal argument. This usually means the entity was not persisted/flushed before its id was read.

Solutions

  1. Ensure the entity is persisted and the EntityManager is flushed before setting it as a process variable so the PK is populated.
  2. Use database-assigned ids (@GeneratedValue) and commit the transaction before variable creation.
  3. If id is generated in-app (e.g. UUID), assign it before the entity is used as a variable.
  4. Catch ActivitiIllegalArgumentException and surface a clearer message about the unpersisted entity.

Example fix

// before
MyEntity e = new MyEntity();
runtimeService.setVariable(executionId, "entity", e); // e.getId() == null
// after
entityManager.persist(e);
entityManager.flush(); // id now populated
runtimeService.setVariable(executionId, "entity", e);
Defensive patterns

Strategy: validation

Validate before calling

if (entity == null || entity.getId() == null) throw new IllegalArgumentException("Entity PK not populated; persist and flush before setting as variable");

Type guard

boolean hasId(MyEntity e) { return e != null && e.getId() != null; }

Prevention

When it happens

Trigger: Setting a process variable to a JPA entity whose @Id field is still null (e.g. a newly created entity that was never persisted, or persistence context not flushed so the DB-assigned id is not yet populated).

Common situations: Storing a new entity created with new/entityManager.persist without flush; forgetting @GeneratedValue or flush before variable assignment; using the JPA variable type in tests without a properly configured EntityManagerSession flush.

Related errors


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

Appendix: source

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

            return Character.valueOf(string.charAt(0));
        } else if (type == java.util.Date.class) {
            return new java.util.Date(Long.parseLong(string));
        } else if (type == java.sql.Date.class) {
            return new java.sql.Date(Long.parseLong(string));
        } else if (type == BigDecimal.class) {
            return new BigDecimal(string);
        } else if (type == BigInteger.class) {
            return new BigInteger(string);
        } else if (type == UUID.class) {
            return UUID.fromString(string);
        } else {
            throw new ActivitiIllegalArgumentException("Unsupported Primary key type for JPA-Entity: " + type.getName());
        }
    }

    public String getIdString(Object value) {
        if (value == null) {
            throw new ActivitiIllegalArgumentException("Value of primary key for JPA-Entity cannot be null");
        }
        // Only java.sql.date and java.util.date require custom handling, the other types
        // can just use toString()
        if (value instanceof java.util.Date) {
            return String.valueOf(((java.util.Date) value).getTime());
        } else if (value instanceof java.sql.Date) {
            return String.valueOf(((java.sql.Date) value).getTime());
        } else if (value instanceof Long || value instanceof String || value instanceof Byte
                || value instanceof Short || value instanceof Integer || value instanceof Float
                || value instanceof Double || value instanceof Character || value instanceof BigDecimal
                || value instanceof BigInteger
                || value instanceof UUID) {
            return value.toString();
        } else {
            throw new ActivitiIllegalArgumentException("Unsupported Primary key type for JPA-Entity: " + value.getClass().getName());
        }
    }
}

View on GitHub (pinned to d6d39ce1c6)