spring-projects/spring-security · error · IllegalStateException
Could not locate field 'X' on class Y
Error message
Could not locate field 'X' on class Y
What it means
FieldUtils.getField walks the class hierarchy (superclasses) looking for a declared field by name; if neither the class nor any superclass declares it, it throws IllegalStateException('Could not locate field X on class Y'). This utility is intended for testing/reflection use, so the exception signals the assumed field genuinely does not exist on the type (or its name was mistyped).
Source
Thrown at core/src/main/java/org/springframework/security/util/FieldUtils.java:55
/**
* Attempts to locate the specified field on the class.
* @param clazz the class definition containing the field
* @param fieldName the name of the field to locate
* @return the Field (never null)
* @throws IllegalStateException if field could not be found
*/
public static Field getField(Class<?> clazz, String fieldName) throws IllegalStateException {
Assert.notNull(clazz, "Class required");
Assert.hasText(fieldName, "Field name required");
try {
return clazz.getDeclaredField(fieldName);
}
catch (NoSuchFieldException ex) {
// Try superclass
if (clazz.getSuperclass() != null) {
return getField(clazz.getSuperclass(), fieldName);
}
throw new IllegalStateException("Could not locate field '" + fieldName + "' on class " + clazz);
}
}
/**
* Returns the value of a (nested) field on a bean. Intended for testing.
* @param bean the object
* @param fieldName the field name, with "." separating nested properties
* @return the value of the nested field
*/
public static Object getFieldValue(Object bean, String fieldName) throws IllegalAccessException {
Assert.notNull(bean, "Bean cannot be null");
Assert.hasText(fieldName, "Field name required");
String[] nestedFields = StringUtils.tokenizeToStringArray(fieldName, ".");
Class<?> componentClass = bean.getClass();
Object value = bean;
for (String nestedField : nestedFields) {
Field field = getField(componentClass, nestedField);
field.setAccessible(true);View on GitHub (pinned to 96852e8860)
Solutions
- Correct the field name and verify the declaring class with clazz.getDeclaredFields() before the call
- Call getField against the actual declaring class rather than a subclass/interface
- Use standard reflection with setAccessible(true) or the Spring ReflectionUtils if you need interface-declared or more flexible lookup
- Replace reflection with a getter/public API where available to remove fragility
Example fix
// before Object v = FieldUtils.getField(bean, "usrName"); // typo -> IllegalStateException // after Object v = FieldUtils.getField(bean, "userName");
Defensive patterns
Strategy: try-catch
Validate before calling
boolean declared = false;
for (Class<?> c = bean.getClass(); c != null; c = c.getSuperclass()) {
try { c.getDeclaredField("userName"); declared = true; break; }
catch (NoSuchFieldException ignored) { }
}
if (!declared) throw new IllegalStateException("Field 'userName' not found"); Type guard
static boolean hasField(Class<?> clazz, String name) {
for (Class<?> c = clazz; c != null; c = c.getSuperclass()) {
try { c.getDeclaredField(name); return true; }
catch (NoSuchFieldException ignored) { }
}
return false;
} Try / catch
try {
Object value = FieldUtils.getField(bean, "userName");
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Could not locate field")) {
// fall back to getter or fail the test with a clear message
} else { throw e; }
} Prevention
- Prefer getters/public APIs over reflective field access
- Re-verify reflected field names after refactors (search usages of FieldUtils)
- Remember the walk covers classes (superclasses), not interfaces
- Add a smoke test that resolves every reflected field name used in test helpers
When it happens
Trigger: Calling FieldUtils.getField(bean, "fieldName") where the target class (and all superclasses) lack that field; typos or renamed/refactored fields not updated at the reflection call site; accessing a nested field via dotted path where an intermediate segment's type does not declare the next field; library upgrade changed an internal field name.
Common situations: Test helpers asserting on private/internal state after refactoring; accessing framework internals (e.g., inside Spring Security filters) that changed between versions; reflection on fields that are inherited through interfaces rather than classes (which the superclass walk does not cover).
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Cannot apply {configurer} to already built object
- This object has already been built
- This object has not been built
- Cannot configure both a CorsConfigurationSource and a PreFli
- Headers security is enabled, but no headers will be added. E
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/6ffa91a6c342740f.
Report an issue: GitHub.