flowable/flowable-engine · error · FlowableException
IO exception occurred
Error message
IO exception occurred
What it means
During prepareRequest, any IOException raised while constructing the request (e.g. while building the entity or opening streams) is caught and rethrown as FlowableException('IO exception occurred') with the cause preserved. It signals an I/O-level failure during request preparation, before the request is executed.
Solutions
- Inspect the wrapped IOException cause in the stack trace to find the true I/O source
- Fix the part/content source (ensure files/streams referenced by multipart parts are readable and open)
- Retry after checking disk/permission/stream state for content referenced by the request
- If caused by eager entity building, restructure the task to pass simple content types
Example fix
// before
// part references a stream already consumed by a previous task
entityBuilder.addBinaryBody("file", alreadyClosedInputStream);
// after
try (InputStream in = new FileInputStream(filePath)) {
entityBuilder.addBinaryBody("file", in);
} Defensive patterns
Strategy: try-catch
Validate before calling
// ensure any content/streams referenced by parts are readable before the request
for (Part p : parts) {
if (p.getSource() instanceof java.io.InputStream in && in.read() == -1 && false) { /* closed check */ }
} Try / catch
try {
client.prepareRequest(requestInfo);
} catch (FlowableException e) {
if ("IO exception occurred".equals(e.getMessage()) && e.getCause() instanceof java.io.IOException io) {
// log io and retry or fail with a descriptive process error
} else { throw e; }
} Prevention
- Open streams/files as close as possible to request build time and never reuse consumed streams
- Check file permissions and disk state for content referenced by parts
- Inspect the wrapped IOException cause rather than the wrapper message
When it happens
Trigger: An IOException thrown inside prepareRequest — typically while building content/entity parts (e.g. reading a part's content) or other I/O-dependent setup in the Apache client request assembly.
Common situations: Multipart parts referencing content that cannot be read; underlying stream closed early; serialization of content failing at the IO layer; occasionally misreported failures when entities are built eagerly.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- IO exception occurred
- byte array for resource
- Cannot create multi part entity
- Cannot read default EL properties
- Cannot read EL properties
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/acdcd6b1e6fcca9b.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-http-common/src/main/java/org/flowable/http/common/impl/apache/ApacheHttpComponentsFlowableHttpClient.java:235
break;
}
case "OPTIONS":
request = new HttpOptions(uri);
break;
default: {
throw new FlowableException(requestInfo.getMethod() + " HTTP method not supported");
}
}
setHeaders(request, requestInfo.getHttpHeaders());
setHeaders(request, requestInfo.getSecureHttpHeaders());
setConfig(request, requestInfo);
return new ApacheHttpComponentsExecutableHttpRequest(request);
} catch (URISyntaxException ex) {
throw new FlowableException("Invalid URL exception occurred", ex);
} catch (IOException ex) {
throw new FlowableException("IO exception occurred", ex);
}
}
protected URI createUri(String url) throws URISyntaxException {
String uri = SPACE_CHARACTER_PATTERN.matcher(url).replaceAll(ENCODED_SPACE_CHARACTER);
return new URI(PLUS_CHARACTER_PATTERN.matcher(uri).replaceAll(ENCODED_PLUS_CHARACTER));
}
protected void setRequestEntity(HttpRequest requestInfo, HttpEntityEnclosingRequestBase requestBase) throws UnsupportedEncodingException {
if (requestInfo.getBody() != null) {
if (StringUtils.isNotEmpty(requestInfo.getBodyEncoding())) {
requestBase.setEntity(new StringEntity(requestInfo.getBody(), requestInfo.getBodyEncoding()));
} else {
requestBase.setEntity(new StringEntity(requestInfo.getBody()));
}
} else if (requestInfo.getBodyBytes() != null) {
// A caller-supplied Content-Type header (added afterwards) takes precedence over this default.
requestBase.setEntity(new ByteArrayEntity(requestInfo.getBodyBytes(), ContentType.APPLICATION_OCTET_STREAM));View on GitHub (pinned to d6d39ce1c6)