{"record":{"id":"73be483acd63a008","repo":"flowable/flowable-engine","slug":"ackmode-in-definition-channeldefinition-must","errorCode":null,"errorMessage":"ackMode in definition [ <channelDefinition> ] must resolve to a String or AcknowledgeMode","messagePattern":"ackMode in definition \\[ <channelDefinition> \\] must resolve to a String or AcknowledgeMode","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-event-registry-spring/src/main/java/org/flowable/eventregistry/spring/rabbit/RabbitChannelDefinitionProcessor.java","lineNumber":246,"sourceCode":"                throw new IllegalArgumentException(\"Could not register rabbit listener endpoint on [\" +\n                    channelDefinition + \"], no \" + RabbitAdmin.class.getSimpleName() + \" with id '\" +\n                    rabbitAdmin + \"' was found in the application context\", ex);\n            }\n        } else {\n            return null;\n        }\n    }\n\n    protected AcknowledgeMode resolveAckMode(RabbitInboundChannelModel channelDefinition) {\n        String ackModeAttr = channelDefinition.getAckMode();\n        if (StringUtils.hasText(ackModeAttr)) {\n            Object ackMode = resolveExpression(ackModeAttr);\n            if (ackMode instanceof String) {\n                return AcknowledgeMode.valueOf((String) ackMode);\n            } else if (ackMode instanceof AcknowledgeMode) {\n                return (AcknowledgeMode) ackMode;\n            } else {\n                throw new IllegalArgumentException(\"ackMode in definition [ \" + channelDefinition + \" ] must resolve to a String or AcknowledgeMode\");\n            }\n        } else {\n            return null;\n        }\n    }\n\n    protected TaskExecutor resolveExecutor(RabbitInboundChannelModel channelDefinition) {\n        String executorBeanName = resolve(channelDefinition.getExecutor());\n        if (StringUtils.hasText(executorBeanName)) {\n            Assert.state(this.beanFactory != null, \"BeanFactory must be set to resolve TaskExecutor by bean name\");\n            try {\n                return this.beanFactory.getBean(executorBeanName, TaskExecutor.class);\n            } catch (NoSuchBeanDefinitionException ex) {\n                throw new IllegalArgumentException(\"Could not register rabbit listener endpoint on [\" +\n                    channelDefinition + \"], no \" + TaskExecutor.class.getSimpleName() + \" with id '\" +\n                    executorBeanName + \"' was found in the application context\", ex);\n            }\n        } else {","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-event-registry-spring/src/main/java/org/flowable/eventregistry/spring/rabbit/RabbitChannelDefinitionProcessor.java#L228-L264","documentation":"The ackMode attribute of a Rabbit inbound channel definition, when set (even as an expression), must resolve to either a String naming an AcknowledgeMode enum value or an AcknowledgeMode instance itself. Any other resolved type makes resolveAckMode throw this IllegalArgumentException.","triggerScenarios":"channelDefinition.getAckMode() expression resolves to a non-String/non-AcknowledgeMode object (e.g. Integer, Boolean) while processing the channel definition in createRabbitListenerEndpoint.","commonSituations":"Config file storing ackMode as a boolean or number; placeholder resolving to the wrong bean; confusion between ack mode names and other frameworks' ackMode types.","solutions":["Set ackMode to a valid string enum name: AUTO, MANUAL, or NONE","Reference an AcknowledgeMode bean directly in the definition","Fix the expression/placeholder so it resolves to the correct type","Check the config serialization so ackMode is emitted as a string, not a number/boolean"],"exampleFix":"// before\n\"ackMode\": true\n// after\n\"ackMode\": \"AUTO\"","handlingStrategy":"validation","validationCode":"Object ack = resolveExpression(channelDefinition.getAckMode());\nif (ack != null && !(ack instanceof String) && !(ack instanceof AcknowledgeMode)) {\n    throw new IllegalArgumentException(\"ackMode must be a String enum name or AcknowledgeMode\");\n}\nif (ack instanceof String) { AcknowledgeMode.valueOf((String) ack); } // validates enum name early","typeGuard":"boolean isValidAckMode(Object v) {\n    return v instanceof AcknowledgeMode || (v instanceof String && Arrays.stream(AcknowledgeMode.values()).anyMatch(m -> m.name().equals(v)));\n}","tryCatchPattern":"try {\n    processor.process(definition);\n} catch (IllegalArgumentException ex) {\n    if (ex.getMessage().contains(\"ackMode\")) {\n        log.error(\"Bad ackMode in {}: {}\", definition, ex.getMessage());\n    }\n    throw ex;\n}","preventionTips":["Store ackMode as a string enum name: AUTO, MANUAL, or NONE","Ensure config serialization writes ackMode as a string, not boolean/number","Validate enum fields against allowed values at config load time"],"tags":["rabbitmq","spring","configuration","enum"],"backgroundTag":"invalid-enum-value","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}