flowable/flowable-engine · error · UncheckedIOException

Failed to read resource ${resource}

Error message

Failed to read resource ${resource}

What it means

During Spring AOT processing, FlowableProcessAutoDeployBeanFactoryInitializationAotProcessor.applyToResource parses each auto-deploy BPMN resource with BpmnXMLConverter to detect delegate-expression service tasks and register reflection hints. If resource.getInputStream() throws IOException it is wrapped as UncheckedIOException 'Failed to read resource <resource>'. The BPMN file exists on the classpath but its stream cannot be opened.

Source

Thrown at modules/flowable-spring-boot/flowable-spring-boot-starters/flowable-spring-boot-autoconfigure/src/main/java/org/flowable/spring/boot/aot/process/FlowableProcessAutoDeployBeanFactoryInitializationAotProcessor.java:93

    static class ProcessAutoDeployResourceContribution extends BaseAutoDeployResourceContribution {

        protected final ConfigurableListableBeanFactory beanFactory;

        public ProcessAutoDeployResourceContribution(String locationPrefix, Collection<String> locationSuffixes, ConfigurableListableBeanFactory beanFactory) {
            super(locationPrefix, locationSuffixes);
            this.beanFactory = beanFactory;
        }

        @Override
        protected void applyToResource(ClassPathResource resource, RuntimeHints hints) {
            super.applyToResource(resource, hints);
            BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
            BpmnModel bpmnModel = xmlConverter.convertToBpmnModel(() -> {
                try {
                    return resource.getInputStream();
                } catch (IOException e) {
                    throw new UncheckedIOException("Failed to read resource " + resource, e);
                }
            }, false, false);
            Collection<ServiceTask> serviceTasks = bpmnModel.getMainProcess().findFlowElementsOfType(ServiceTask.class);
            for (ServiceTask serviceTask : serviceTasks) {
                if (ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION.equals(serviceTask.getImplementationType())) {
                    String expression = serviceTask.getImplementation();
                    String expressionWithoutDelimiters = expression.substring(2);
                    expressionWithoutDelimiters = expressionWithoutDelimiters.substring(0, expressionWithoutDelimiters.length() - 1);
                    String beanName = expressionWithoutDelimiters;
                    try {
                        BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
                        String beanClassName = beanDefinition.getBeanClassName();
                        if (StringUtils.isNotEmpty(beanClassName)) {
                            hints.reflection().registerType(TypeReference.of(beanClassName), MemberCategory.values());
                            logger.debug("Registering hint for bean name [{}] for service task {} in {}", beanName, serviceTask.getId(), resource);
                        } else {
                            logger.debug("No bean class name for bean name [{}] for service task {} in {}", beanName, serviceTask.getId(), resource);
                        }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Run a clean rebuild (mvn clean install) so the jar containing the BPMN files is consistent
  2. Verify BPMN resources are present and readable in the artifact (jar tf / unzip -t)
  3. Check file permissions and disk space on the build machine
  4. Ensure Spring Boot AOT and Flowable versions are compatible and current
Defensive patterns

Strategy: try-catch

Validate before calling

ClassPathResource r = new ClassPathResource("processes/my-process.bpmn20.xml");
if (!r.exists() || !r.getFile().canRead()) {
    throw new IllegalStateException("BPMN resource missing or unreadable: " + r);
}

Try / catch

try (InputStream in = resource.getInputStream()) {
    // parse bpmn model
} catch (UncheckedIOException | IOException e) {
    logger.error("Cannot read BPMN resource {}", resource, e);
}

Prevention

When it happens

Trigger: AOT/native-image build where the converter's supplier calls getInputStream() on a classpath .bpmn/.bpmn20.xml resource and IO fails (broken jar entry, unavailable nested resource, permission error).

Common situations: GraalVM native builds on CI with inconsistent artifacts; corrupted target jar after interrupted build; resources inside nested jars; restrictive file permissions.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/b45f3b56c6cc61a7. Report an issue: GitHub.