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
- Run a clean rebuild (mvn clean install) so the jar containing the BPMN files is consistent
- Verify BPMN resources are present and readable in the artifact (jar tf / unzip -t)
- Check file permissions and disk space on the build machine
- 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
- Run mvn clean before release/AOT builds to prevent corrupted jars
- Verify BPMN resources inside the built artifact, not just in src
- Keep Spring Boot AOT and Flowable plugin versions aligned
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
- Failed to read resource ${resource}
- Failed to read mappings
- Failed to read mapper from
- Failed to find resources for ${path}
- Failed to read resource <resource>
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/b45f3b56c6cc61a7.
Report an issue: GitHub.