{"record":{"id":"ed82a0728276673f","repo":"flowable/flowable-engine","slug":"value-of-primary-key-for-jpa-entity-cannot-be-null-ed82a0","errorCode":null,"errorMessage":"Value of primary key for JPA-Entity cannot be null","messagePattern":"Value of primary key for JPA-Entity cannot be null","errorType":"exception","errorClass":"ActivitiIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/variable/JPAEntityMappings.java","lineNumber":176,"sourceCode":"            return Character.valueOf(string.charAt(0));\n        } else if (type == java.util.Date.class) {\n            return new java.util.Date(Long.parseLong(string));\n        } else if (type == java.sql.Date.class) {\n            return new java.sql.Date(Long.parseLong(string));\n        } else if (type == BigDecimal.class) {\n            return new BigDecimal(string);\n        } else if (type == BigInteger.class) {\n            return new BigInteger(string);\n        } else if (type == UUID.class) {\n            return UUID.fromString(string);\n        } else {\n            throw new ActivitiIllegalArgumentException(\"Unsupported Primary key type for JPA-Entity: \" + type.getName());\n        }\n    }\n\n    public String getIdString(Object value) {\n        if (value == null) {\n            throw new ActivitiIllegalArgumentException(\"Value of primary key for JPA-Entity cannot be null\");\n        }\n        // Only java.sql.date and java.util.date require custom handling, the other types\n        // can just use toString()\n        if (value instanceof java.util.Date) {\n            return String.valueOf(((java.util.Date) value).getTime());\n        } else if (value instanceof java.sql.Date) {\n            return String.valueOf(((java.sql.Date) value).getTime());\n        } else if (value instanceof Long || value instanceof String || value instanceof Byte\n                || value instanceof Short || value instanceof Integer || value instanceof Float\n                || value instanceof Double || value instanceof Character || value instanceof BigDecimal\n                || value instanceof BigInteger\n                || value instanceof UUID) {\n            return value.toString();\n        } else {\n            throw new ActivitiIllegalArgumentException(\"Unsupported Primary key type for JPA-Entity: \" + value.getClass().getName());\n        }\n    }\n}","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/variable/JPAEntityMappings.java#L158-L194","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Ensure the entity is persisted and the EntityManager is flushed before setting it as a process variable so the PK is populated.","Use database-assigned ids (@GeneratedValue) and commit the transaction before variable creation.","If id is generated in-app (e.g. UUID), assign it before the entity is used as a variable.","Catch ActivitiIllegalArgumentException and surface a clearer message about the unpersisted entity."],"exampleFix":"// before\nMyEntity e = new MyEntity();\nruntimeService.setVariable(executionId, \"entity\", e); // e.getId() == null\n// after\nentityManager.persist(e);\nentityManager.flush(); // id now populated\nruntimeService.setVariable(executionId, \"entity\", e);","handlingStrategy":"validation","validationCode":"if (entity == null || entity.getId() == null) throw new IllegalArgumentException(\"Entity PK not populated; persist and flush before setting as variable\");","typeGuard":"boolean hasId(MyEntity e) { return e != null && e.getId() != null; }","tryCatchPattern":null,"preventionTips":["Always persist+flush entities before storing them as process variables","Use @GeneratedValue so the provider assigns ids early","Prefer storing entity ids as plain variables when possible"],"tags":["jpa","null-value","variables"],"backgroundTag":"null-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}