flowable/flowable-engine · error · FlowableException

Error converting resource stream

Error message

Error converting resource stream

What it means

When the resource exists in the deployment, the endpoint streams it via repositoryService.getResourceAsStream and reads it with IOUtils.toByteArray. Any exception during that I/O (closed stream, storage backend failure, corruption) is wrapped in a FlowableException with message 'Error converting resource stream', preserving the cause and surfacing as HTTP 500.

Source

Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/repository/BaseDeploymentResourceDataResource.java:74

        if (deployment == null) {
            throw new FlowableObjectNotFoundException("Could not find a deployment with id '" + deploymentId + "'.", CmmnDeployment.class);
        }
        
        if (restApiInterceptor != null) {
            restApiInterceptor.accessDeploymentById(deployment);
        }

        List<String> resourceList = repositoryService.getDeploymentResourceNames(deploymentId);

        if (resourceList.contains(resourceName)) {
            String contentType = contentTypeResolver.resolveContentType(resourceName);
            response.setContentType(contentType);
            
            try (final InputStream resourceStream = repositoryService.getResourceAsStream(deploymentId, resourceName)) {
                return IOUtils.toByteArray(resourceStream);
                
            } catch (Exception e) {
                throw new FlowableException("Error converting resource stream", e);
            }
            
        } else {
            // Resource not found in deployment
            throw new FlowableObjectNotFoundException("Could not find a resource with name '" + resourceName + "' in deployment '" + deploymentId + "'.", String.class);
        }
    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Inspect the wrapped cause in the server log/HTTP 500 response to find the underlying I/O problem.
  2. Verify database/storage health and re-check connectivity used by the Flowable engine.
  3. Re-deploy the resource to recreate its byte content, then retry the request.
  4. Retry the request if the failure was transient (connection reset, temporary DB outage).

Example fix

// before
byte[] data = get("/cmmn-repository/deployments/" + id + "/res/" + name).body(); // 500, no retry
// after
try {
  byte[] data = get(url).body();
} catch (HttpServerErrorException e) {
  data = retry(url, 3); // transient stream/storage failures
}
Defensive patterns

Strategy: retry

Try / catch

try {
  return await fetchResourceData(deploymentId, name);
} catch (e) {
  if (e.response?.status === 500 && /Error converting resource stream/.test(e.response.data?.message)) {
    await sleep(backoff(attempt));
    return fetchResourceData(deploymentId, name); // retry transient I/O
  }
  throw e;
}

Prevention

When it happens

Trigger: GET /cmmn-repository/deployments/{deploymentId}/res/{resourceName} where the resource record exists but its underlying byte content cannot be read from the deployment store (database blob, filesystem).

Common situations: Database connectivity drops mid-read; a manually pruned/corrupted ACT_GE_BYTEARRAY row; storage migration left content missing; very large resources hitting timeouts or memory limits.

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/5e71968dc4094f64. Report an issue: GitHub.