{"record":{"id":"38b64e7fb011fbd1","repo":"flowable/flowable-engine","slug":"incompatible-type-set-on-field-declaration-s-fo-38b64e","errorCode":null,"errorMessage":"Incompatible type set on field declaration '%s' for class %s. Declared value has type %s, while expecting %s","messagePattern":"Incompatible type set on field declaration '(.+?)' for class (.+?)\\. Declared value has type (.+?), while expecting (.+?)","errorType":"validation","errorClass":"ActivitiIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegateUtil.java","lineNumber":69,"sourceCode":"\n        if (setterMethod != null) {\n            try {\n                setterMethod.invoke(target, declaration.getValue());\n            } catch (IllegalArgumentException e) {\n                throw new ActivitiException(\"Error while invoking '\" + declaration.getName() + \"' on class \" + target.getClass().getName(), e);\n            } catch (IllegalAccessException e) {\n                throw new ActivitiException(\"Illegal access when calling '\" + declaration.getName() + \"' on class \" + target.getClass().getName(), e);\n            } catch (InvocationTargetException e) {\n                throw new ActivitiException(\"Exception while invoking '\" + declaration.getName() + \"' on class \" + target.getClass().getName(), e);\n            }\n        } else {\n            Field field = ReflectUtil.getField(declaration.getName(), target);\n            if (field == null) {\n                throw new ActivitiIllegalArgumentException(\"Field definition uses unexisting field '\" + declaration.getName() + \"' on class \" + target.getClass().getName());\n            }\n            // Check if the delegate field's type is correct\n            if (!fieldTypeCompatible(declaration, field)) {\n                throw new ActivitiIllegalArgumentException(\"Incompatible type set on field declaration '\" + declaration.getName()\n                        + \"' for class \" + target.getClass().getName()\n                        + \". Declared value has type \" + declaration.getValue().getClass().getName()\n                        + \", while expecting \" + field.getType().getName());\n            }\n            ReflectUtil.setField(field, target, declaration.getValue());\n        }\n    }\n\n    public static boolean fieldTypeCompatible(FieldDeclaration declaration, Field field) {\n        if (declaration.getValue() != null) {\n            return field.getType().isAssignableFrom(declaration.getValue().getClass());\n        } else {\n            // Null can be set any field type\n            return true;\n        }\n    }\n\n}","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegateUtil.java#L51-L87","documentation":"Thrown when the value injected via a BPMN field declaration has a Java type incompatible with the declared field on the delegate class. fieldTypeCompatible() fails and the engine refuses to set the field with ActivitiIllegalArgumentException, reporting both types.","triggerScenarios":"A flowable:field supplies e.g. a String or expression value where the delegate field's type is incompatible (e.g. int field given a non-numeric String, or a String value into a custom object field), and no converter matches.","commonSituations":"Injecting stringValue into a numeric/boolean field without a matching type; using expression results whose runtime type differs from the field type; changing a field's type in the delegate after processes were deployed.","solutions":["Make the injected value's type match the field type (e.g. use flowable:string for String fields, numeric literal for int)","Change the delegate field type to accept the value being injected (e.g. String field, parse later)","Use an expression that evaluates to the field's declared type","If injection happens via setter, convert inside the setter"],"exampleFix":"// before\n<flowable:field name=\"retryCount\" stringValue=\"3\"/> <!-- int field, String value -->\n// after\n<flowable:field name=\"retryCount\"><flowable:value>3</flowable:value></flowable:field>","handlingStrategy":"validation","validationCode":"java.lang.reflect.Field f = delegateClass.getDeclaredField(\"retryCount\");\nObject injected = \"3\";\nif (!f.getType().isInstance(injected) && !(injected instanceof String)) throw new IllegalStateException(\"type mismatch for \" + f.getName());","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use flowable:string/string/expr attributes matching the field's Java type","Keep field types stable across versions or migrate process definitions","Prefer String fields and parse in the delegate to avoid type coupling"],"tags":["java","bpmn","field-injection","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}