flowable/flowable-engine · error · FlowableIllegalArgumentException

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

getIdString serializes a JPA entity's primary key value to a string for storage in a Flowable variable row. If the @Id value on the entity instance is null, Flowable cannot persist or look up the variable reference, so it throws immediately.

Source

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

            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 FlowableIllegalArgumentException("Unsupported Primary key type for JPA-Entity: " + type.getName());
        }
    }

    public String getIdString(Object value) {
        if (value == null) {
            throw new FlowableIllegalArgumentException("Value of primary key for JPA-Entity cannot be null");
        }
        // Only java.util.Date requires 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 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 FlowableIllegalArgumentException("Unsupported Primary key type for JPA-Entity: " + value.getClass().getName());
        }
    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Persist the entity and flush the EntityManager before assigning it to the Flowable variable, so the id generator has populated the @Id.
  2. Confirm the entity was saved in the same command context whose EntityManagerSession Flowable uses (JPAEntityVariableType.flushes pending changes on setValue).
  3. Add a null check on the entity's id in your own code before setting the variable and fail fast with a clearer message.
  4. For manually assigned ids, ensure application code always sets the id before the entity is used as a variable value.

Example fix

// before
processEngine.getTaskService().setVariable(taskId, "entity", new Customer()); // id null
// after
Customer c = new Customer();
entityManager.persist(c);
entityManager.flush(); // id now assigned
processEngine.getTaskService().setVariable(taskId, "entity", c);
Defensive patterns

Strategy: validation

Validate before calling

Object id = entityManager.getEntityManagerFactory().getPersistenceUnitUtil().getIdentifier(entity);
if (id == null) throw new IllegalStateException("Entity id not assigned; persist+flush before storing as Flowable variable");

Type guard

boolean hasId(Object e) { return emf.getPersistenceUnitUtil().getIdentifier(e) != null; }

Try / catch

try { taskService.setVariable(taskId, "entity", entity); } catch (FlowableIllegalArgumentException e) { if (e.getMessage().contains("cannot be null")) { em.flush(); taskService.setVariable(taskId, "entity", entity); } else throw e; }

Prevention

When it happens

Trigger: Calling getJPAIdString on an entity instance whose @Id field/getter returns null — typically a newly created (not yet persisted/flushed) entity, or an entity whose id was never assigned.

Common situations: Passing a `new SomeEntity()` to Flowable's setValue before save; missing EntityManager flush so the @GeneratedValue id is not yet populated; entities saved with a different EntityManager than the one Flowable flushed.

Related errors


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