{"record":{"id":"351f5df7b6e8ee95","repo":"flowable/flowable-engine","slug":"expected-expression-expression-to-resolve-to","errorCode":null,"errorMessage":"expected expression ${expression} to resolve to ${type} but it did not. Resolved value is ${value}","messagePattern":"expected expression (.+?) to resolve to (.+?) but it did not\\. Resolved value is (.+?)","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-event-registry/src/main/java/org/flowable/eventregistry/impl/pipeline/InboundChannelModelProcessor.java","lineNumber":379,"sourceCode":"                        + \". One of fixedValue, jsonField, jsonPointerExpression, xmlXPathExpression, delegateExpression should be set.\");\n            }\n        }\n\n        //noinspection unchecked\n        return new DefaultInboundEventProcessingPipeline(eventRepositoryService, eventDeserializer, eventFilter,\n            eventKeyDetector, eventTenantDetector, eventPayloadExtractor, eventTransformer, engineConfiguration);\n    }\n\n    protected <T> T resolveExpression(String expression, Class<T> type) {\n        Object value = CommandContextUtil.getEventRegistryConfiguration().getExpressionManager()\n            .createExpression(expression)\n            .getValue(new VariableContainerWrapper(Collections.emptyMap()));\n\n        if (type.isInstance(value)) {\n            return type.cast(value);\n        }\n\n        throw new FlowableException(\"expected expression \" + expression + \" to resolve to \" + type + \" but it did not. Resolved value is \" + value);\n\n    }\n\n    @Override\n    public void unregisterChannelModel(ChannelModel channelModel, String tenantId, EventRepositoryService eventRepositoryService) {\n        // nothing to do\n    }\n}\n","sourceCodeStart":361,"sourceCodeEnd":388,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-event-registry/src/main/java/org/flowable/eventregistry/impl/pipeline/InboundChannelModelProcessor.java#L361-L388","documentation":"InboundChannelModelProcessor.resolveExpression evaluates a delegate expression (e.g. a Spring/el bean reference) and verifies the resolved value is an instance of the requested type (such as InboundEventKeyDetector, InboundEventSerializer, or a payload extractor). If the expression resolves to something of a different type (or null), Flowable throws this FlowableException instead of returning a bad cast.","triggerScenarios":"Any channel registration/pipeline creation that resolves a delegateExpression — e.g. serializerDelegateExpression, keyDetector delegateExpression, payload extractor expression — where the bean behind the expression does not implement/extend the expected interface, or the expression evaluates to null.","commonSituations":"Pointing a delegateExpression at the wrong Spring bean (right name, wrong type); bean of a compatible-looking custom class that does not implement Flowable's interface; expression typo resolving to a String; bean not yet created so expression resolves null.","solutions":["Make the referenced bean implement the exact expected interface (e.g. implements InboundEventKeyDetector) and redeploy","Check the expression string for typos and confirm it points at the intended bean; verify the bean exists in the application context and is of the expected type","Log the resolved value's class at that expression to diagnose the mismatch, then correct the configuration or the bean"],"exampleFix":"// before\n@Bean\npublic Object orderKeyDetector() { return new OrderKeyResolver(); } // wrong type\n// after\n@Bean\npublic InboundEventKeyDetector orderKeyDetector() { return new OrderKeyResolver(); } // implements InboundEventKeyDetector","handlingStrategy":"validation","validationCode":"Object resolved = applicationContext.getBean(beanName);\nif (!(resolved instanceof InboundEventKeyDetector)) {\n    throw new IllegalArgumentException(beanName + \" must implement InboundEventKeyDetector, got \" + resolved.getClass());\n}","typeGuard":"boolean validDelegate = obj instanceof InboundEventKeyDetector;","tryCatchPattern":"try {\n    registerChannelModel(channelModel, tenantId, repoService);\n} catch (FlowableException e) {\n    if (e.getMessage().startsWith(\"expected expression\")) {\n        // inspect bean type behind the delegateExpression\n    } else { throw e; }\n}","preventionTips":["Type delegate beans as the exact Flowable interface in @Bean method return types","Ensure referenced beans exist in the context before channel registration","Smoke-test delegate expressions at application startup"],"tags":["flowable","expression","type-mismatch","spring-bean"],"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"}