flowable/flowable-engine · error · org.activiti.engine.ActivitiException

Couldn't read file

Error message

Couldn't read file ${filePath}: ${e.getMessage()}

What it means

IoUtil.readFileAsString loads a classpath-relative file into a String via a BufferedInputStream. Any failure opening or reading the file (missing file, permission, IO error) is rethrown as ActivitiException including the file path and the cause's message.

Solutions

  1. Verify the file exists at the exact classpath-relative path (check spelling and case).
  2. Include the resource in the build (src/main/resources).
  3. For resources inside jars, read via ClassLoader.getResourceAsStream instead of File.
  4. Check file permissions on the target resource.

Example fix

// before
String content = IoUtil.readFileAsString("config/app.properties"); // not packaged
// after (move file to src/main/resources/config/app.properties) or read via stream:
try (InputStream in = IoUtil.class.getClassLoader().getResourceAsStream("config/app.properties")) {
    String content = new String(in.readAllBytes(), StandardCharsets.UTF_8);
}
Defensive patterns

Strategy: validation

Validate before calling

URL url = IoUtil.class.getClassLoader().getResource(filePath);
if (url == null) throw new IllegalStateException("Resource not on classpath: " + filePath);
if (!"file".equals(url.getProtocol())) throw new IllegalStateException("Resource is not file-accessible: " + url);

Try / catch

try {
    String s = IoUtil.readFileAsString(path);
} catch (ActivitiException e) {
    if (e.getMessage().startsWith("Couldn't read file")) { /* fall back to classpath stream */ }
}

Prevention

When it happens

Trigger: Calling IoUtil.readFileAsString(filePath) where the resource resolves on the classpath but FileInputStream fails — file absent at that location, is a directory, or is unreadable.

Common situations: Resources not packaged in the artifact (missing from src/main/resources); case-sensitive classpath mismatches on Linux; reading files inside nested jars which File-based access cannot handle.

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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/util/IoUtil.java:57

            int bytesRead = inputStream.read(buffer);
            while (bytesRead != -1) {
                outputStream.write(buffer, 0, bytesRead);
                bytesRead = inputStream.read(buffer);
            }
        } catch (Exception e) {
            throw new ActivitiException("couldn't read input stream " + inputStreamName, e);
        }
        return outputStream.toByteArray();
    }

    public static String readFileAsString(String filePath) {
        byte[] buffer = new byte[(int) getFile(filePath).length()];
        BufferedInputStream inputStream = null;
        try {
            inputStream = new BufferedInputStream(new FileInputStream(getFile(filePath)));
            inputStream.read(buffer);
        } catch (Exception e) {
            throw new ActivitiException("Couldn't read file " + filePath + ": " + e.getMessage());
        } finally {
            IoUtil.closeSilently(inputStream);
        }
        return new String(buffer);
    }

    public static File getFile(String filePath) {
        URL url = IoUtil.class.getClassLoader().getResource(filePath);
        try {
            return new File(url.toURI());
        } catch (Exception e) {
            throw new ActivitiException("Couldn't get file " + filePath + ": " + e.getMessage());
        }
    }

    public static void writeStringToFile(String content, String filePath) {
        BufferedOutputStream outputStream = null;
        try {

View on GitHub (pinned to d6d39ce1c6)