flowable/flowable-engine · error · FlowableException

not allowed to access field

Error message

not allowed to access field ${field} on class ${clazz.getCanonicalName()}

What it means

ReflectUtil.getField looks up a declared field on a class (recursively checking superclasses). If the JVM SecurityManager denies access to the field (SecurityException from getDeclaredField), it throws this FlowableException; the odd message prints the still-null field variable due to where it's captured.

Solutions

  1. Grant the code reflective permission (ReflectPermission) in your security policy file.
  2. Avoid reflecting into JDK/module-encapsulated classes; add --add-opens flags if you own the module boundary.
  3. Use a public accessor/getter instead of direct field access.
  4. Run without a restrictive SecurityManager if your platform allows (note: deprecated in modern JDKs).
  5. Restructure the target class to expose the field legitimately (package-private + same package, or setter).

Example fix

// before
// security policy denying reflection
grant { };
// after
grant {
  permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
};
Defensive patterns

Strategy: validation

Validate before calling

try {
    clazz.getDeclaredField(fieldName);
} catch (SecurityException e) {
    throw new IllegalStateException("Security policy blocks reflective access to " + fieldName);
} catch (NoSuchFieldException e) {
    throw new IllegalStateException("Field " + fieldName + " not found on " + clazz.getName());
}

Try / catch

try {
    Field f = ReflectUtil.getField(fieldName, clazz);
} catch (FlowableException e) {
    LOGGER.error("Reflective access denied for {}.{}: {}", clazz.getName(), fieldName, e.getCause());
    throw new SecurityConfigurationException("Grant ReflectPermission or avoid JDK-internal classes", e);
}

Prevention

When it happens

Trigger: Calling getField(fieldName, clazz) — directly or indirectly through invokeSetterOrField / field injection — in an environment with a SecurityManager or module restrictions that forbid reflective access to the field (e.g. private fields of JDK-internal or sealed classes).

Common situations: Running under a strict SecurityManager policy (common in some app servers); reflecting into java.* or module-encapsulated classes after JDK 9+; agent/sandboxed environments blocking reflection.

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

Appendix: source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/util/ReflectUtil.java:206

        }
    }

    /**
     * Returns the field of the given object or null if it doesn't exist.
     */
    public static Field getField(String fieldName, Object object) {
        return getField(fieldName, object.getClass());
    }

    /**
     * Returns the field of the given class or null if it doesn't exist.
     */
    public static Field getField(String fieldName, Class<?> clazz) {
        Field field = null;
        try {
            field = clazz.getDeclaredField(fieldName);
        } catch (SecurityException e) {
            throw new FlowableException("not allowed to access field " + field + " on class " + clazz.getCanonicalName(), e);
        } catch (NoSuchFieldException e) {
            // for some reason getDeclaredFields doesn't search superclasses
            // (which getFields() does ... but that gives only public fields)
            Class<?> superClass = clazz.getSuperclass();
            if (superClass != null) {
                return getField(fieldName, superClass);
            }
        }
        return field;
    }

    public static void setField(Field field, Object object, Object value) {
        try {
            field.setAccessible(true);
            field.set(object, value);
        } catch (IllegalArgumentException | IllegalAccessException e) {
            throw new FlowableException("Could not set field " + field, e);
        }

View on GitHub (pinned to d6d39ce1c6)