flowable/flowable-engine · warning · ELException

Could not get context class loader

Error message

Could not get context class loader

What it means

load() resolves a class named in the factory properties and tries to use the thread context class loader (TCCL) to load it. If obtaining the TCCL itself throws (rare: security manager or unusual threading environment), it wraps the exception in ELException 'Could not get context class loader'.

Source

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

			}
		} catch (Exception e) {
			throw new ELException("TreeBuilder " + clazz + " could not be instantiated", e);
		}
	}

	protected TreeBuilder createDefaultTreeBuilder(Feature... features) {
		return new Builder(features);
	}

	private Class<?> load(Class<?> clazz, Properties properties) {
		if (properties != null) {
			String className = properties.getProperty(clazz.getName());
			if (className != null) {
				ClassLoader loader;
				try {
					loader = Thread.currentThread().getContextClassLoader();
				} catch (Exception e) {
					throw new ELException("Could not get context class loader", e);
				}
				try {
					return loader == null ? Class.forName(className) : loader.loadClass(className);
				} catch (ClassNotFoundException e) {
					throw new ELException("Class " + className + " not found", e);
				} catch (Exception e) {
					throw new ELException("Class " + className + " could not be instantiated", e);
				}
			}
		}
		return null;
	}

	@Override
	public final <T> T coerceToType(Object obj, Class<T> targetType) {
		return converter.convert(obj, targetType);
	}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Grant RuntimePermission("getClassLoader") to the application's security policy
  2. Remove or relax the SecurityManager restrictions for the engine's execution context
  3. Set the factory classes explicitly so they resolve without context-loader lookup, or run with a standard thread context

Example fix

// before (java.policy)
grant { };

// after
grant {
  permission java.lang.RuntimePermission "getClassLoader";
};
Defensive patterns

Strategy: try-catch

Validate before calling

try {
    ClassLoader l = Thread.currentThread().getContextClassLoader();
} catch (SecurityException e) {
    throw new IllegalStateException("Security policy denies getClassLoader; grant RuntimePermission before engine init");
}

Try / catch

try {
    ExpressionFactory factory = new ExpressionFactoryImpl();
} catch (ELException e) {
    if (e.getMessage().contains("Could not get context class loader")) {
        throw new IllegalStateException("Review SecurityManager policy: getClassLoader permission required", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: ExpressionFactoryImpl.load() (accessed via the clazz() accessor while resolving property-configured classes) calls Thread.currentThread().getContextClassLoader() and the call throws — typically under a restrictive Java SecurityManager or a container that denies RuntimePermission 'getClassLoader'.

Common situations: Running inside an application server or sandbox with a SecurityManager that blocks context classloader access; exotic custom thread implementations whose getContextClassLoader throws.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/2568b450b2d22536. Report an issue: GitHub.