flowable/flowable-engine · error · ELException

Cannot read EL properties

Error message

Cannot read EL properties

What it means

loadProperties() loads a user-supplied EL properties file (given by path) from the classpath or filesystem. If the stream is found but properties.load() throws an IOException, it wraps it as ELException 'Cannot read EL properties'. Unlike the default-properties variant, the resource here is application-provided.

Source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/de/odysseus/el/ExpressionFactoryImpl.java:299

		}
		return null;
	}

	private Properties loadProperties(String path) {
		Properties properties = new Properties(loadDefaultProperties());

		// try to find and load properties
		InputStream input = null;
		try {
			input = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
		} catch (SecurityException e) {
			input = ClassLoader.getSystemResourceAsStream(path);
		}
		if (input != null) {
			try {
				properties.load(input);
			} catch (IOException e) {
				throw new ELException("Cannot read EL properties", e);
			} finally {
				try {
					input.close();
				} catch (IOException e) {
					// ignore...
				}
			}
		}

		return properties;
	}

	private boolean getFeatureProperty(Profile profile, Properties properties, Feature feature, String property) {
		return Boolean.valueOf(properties.getProperty(property, String.valueOf(profile.contains(feature))));
	}

	/**
	 * Create the factory's tree store. This implementation creates a new tree store using the

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Fix the syntax of the custom properties file — escape special characters and use latin-1/\uXXXX escapes
  2. Validate the file loads standalone with new Properties().load(new FileInputStream(file)) before deploying
  3. Re-copy the resource into the classpath (verify it is not truncated)

Example fix

// before (broken el.properties)
cacheSize=1024
builder=de.odysseus.el.tree.impl
???

// after
de.odysseus.el.tree.impl.TreeStore.cacheSize = 1024
Defensive patterns

Strategy: validation

Validate before calling

// Validate a custom EL properties file before pointing the factory at it
Properties p = new Properties();
try (InputStream in = new FileInputStream("el.properties")) {
    p.load(in); // will throw IOException on malformed content
}

Try / catch

try {
    ExpressionFactory factory = new ExpressionFactoryImpl(props);
} catch (ELException e) {
    if (e.getCause() instanceof IOException) {
        log.error("Custom EL properties file unreadable/malformed", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Creating an ExpressionFactoryImpl (or ExpressionFactory.newInstance) with a Properties entry pointing to a custom EL properties file whose contents cannot be parsed as a java.util.Properties stream — malformed input, wrong encoding, or stream that fails mid-read.

Common situations: Hand-edited juel.properties / EL properties file with invalid syntax or binary garbage; file on classpath with wrong encoding (not ISO-8859-1/escape format); truncated resource copied into the WAR.

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