{"record":{"id":"2233f1d46a1c0bae","repo":"flowable/flowable-engine","slug":"error-while-invoking-s-on-class-s","errorCode":null,"errorMessage":"Error while invoking '%s' on class %s","messagePattern":"Error while invoking '(.+?)' on class (.+?)","errorType":"exception","errorClass":"ActivitiException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java","lineNumber":271,"sourceCode":"            for (FieldDeclaration declaration : fieldDeclarations) {\n                applyFieldDeclaration(declaration, target, throwExceptionOnMissingField);\n            }\n        }\n    }\n\n    public static void applyFieldDeclaration(FieldDeclaration declaration, Object target) {\n        applyFieldDeclaration(declaration, target, true);\n    }\n\n    public static void applyFieldDeclaration(FieldDeclaration declaration, Object target, boolean throwExceptionOnMissingField) {\n        Method setterMethod = ReflectUtil.getSetter(declaration.getName(),\n                target.getClass(), declaration.getValue().getClass());\n\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                if (throwExceptionOnMissingField) {\n                    throw new ActivitiIllegalArgumentException(\"Field definition uses unexisting field '\" + declaration.getName() + \"' on class \" + target.getClass().getName());\n                } else {\n                    return;\n                }\n            }\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()","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/ClassDelegate.java#L253-L289","documentation":"When applying a field declaration (activiti:field extension) to the delegate instance, ClassDelegate first tries setter injection via reflection. If the setter exists but Method.invoke throws IllegalArgumentException (e.g. the declared value's type cannot be converted to the setter's parameter type), this ActivitiException wraps the cause.","triggerScenarios":"A field declaration whose value type does not match the delegate's setter parameter (e.g. string value passed to setCount(int) without matching expression type), causing setterMethod.invoke(target, value) to fail with IllegalArgumentException.","commonSituations":"BPMN XML activiti:field with stringValue/string vs an Expression/Date/int setter; delegate refactored to change setter signature while process XML still declares old type; Spring bean field injection with incompatible EL result.","solutions":["Align the field declaration type with the setter parameter type (use stringValue, expression, or the correct FixedValue type in the BPMN XML).","Change the delegate setter to accept the declared type (e.g. accept Expression or String and convert inside).","Inspect the wrapped IllegalArgumentException cause to identify the exact parameter mismatch."],"exampleFix":"// before (BPMN)\n<activiti:field name=\"count\"><activiti:string>abc</activiti:string></activiti:field>\n// setter: public void setCount(int count)\n// after\n<activiti:field name=\"count\"><activiti:string>42</activiti:string></activiti:field>\n// setter: public void setCount(String count) { this.count = Integer.parseInt(count); }","handlingStrategy":"validation","validationCode":"Method m = delegate.getClass().getMethod(\"set\" + capitalize(fieldName), value.getClass());\n// resolve setter before wiring the field declaration; fail fast on mismatch","typeGuard":"boolean setterAccepts(Object target, String field, Object value) {\n  try { target.getClass().getMethod(\"set\" + Character.toUpperCase(field.charAt(0)) + field.substring(1), value.getClass()); return true; }\n  catch (NoSuchMethodException e) { return false; }\n}","tryCatchPattern":"try {\n  runtimeService.startProcessInstanceByKey(key, vars);\n} catch (ActivitiException e) {\n  if (e.getMessage().startsWith(\"Error while invoking\")) {\n    log.error(\"Field injection type mismatch; check activiti:field value vs setter\", e);\n  } else throw e;\n}","preventionTips":["Keep activiti:field value element type (string/expression) aligned with setter signatures","Add deployment-time validation tests that instantiate delegates with their field declarations","Prefer Expression-typed setters to accept both literals and EL"],"tags":["reflection","field-injection","delegate","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"}