ssssssss-team/spider-flow · error · RuntimeException
Couldn't get value of field '" + javaField.getName() + "'…
Error message
Couldn't get value of field '" + javaField.getName() + "' from object of type '" + obj.getClass().getSimpleName() + "'
What it means
JavaReflection.getFieldValue retrieves a reflective Field's value from an object via Field.get(obj). If the reflective access throws for any reason (illegal access, mismatched object, initializer failure), it wraps it in a RuntimeException naming the field and the object's simple class name.
Solutions
- Ensure the object passed is an instance of the field's declaring class
- Make the field public or call setAccessible(true) on the Field before access
- Add JVM args --add-opens for the relevant package when running on Java 9+
- Catch the RuntimeException at the evaluation call site and log field name plus cause
Example fix
// before
Object v = reflection.getFieldValue(obj, field);
// after
Field f = (Field) field;
f.setAccessible(true);
if (!f.getDeclaringClass().isInstance(obj)) {
throw new IllegalArgumentException(obj + " is not a " + f.getDeclaringClass());
}
Object v = reflection.getFieldValue(obj, field); Defensive patterns
Strategy: try-catch
Validate before calling
if (obj == null || !((Field) field).getDeclaringClass().isInstance(obj)) {
throw new IllegalArgumentException("Object not compatible with field " + field);
} Type guard
boolean canRead(Object obj, Field f) {
return obj != null && f.getDeclaringClass().isInstance(obj);
} Try / catch
try {
Object v = reflection.getFieldValue(obj, field);
} catch (RuntimeException e) {
logger.error("Field access failed: {}", e.getMessage(), e.getCause());
throw new ExpressionEvaluationException("Cannot read field", e);
} Prevention
- Prefer getters over direct field reflection for non-public fields
- Call setAccessible(true) when accessing non-public fields intentionally
- Run on JVM versions/modules that permit the required --add-opens
- Validate object types before reflective access
When it happens
Trigger: Calling getFieldValue(obj, field) where the Field is inaccessible (non-public without setAccessible), obj is not an instance of the declaring class, or the field's class fails to initialize.
Common situations: Expression evaluation accessing object properties on beans with private fields; passing an object of the wrong type; JDK module system blocking reflective access (Java 9+).
Related errors
AI-assisted analysis of ssssssss-team/spider-flow@c799cca99c (2026-09-08).
Data as JSON: /api/errors/c426df80a67cc359.
Report an issue: GitHub.
Appendix: source
Thrown at spider-flow-core/src/main/java/org/spiderflow/core/expression/interpreter/JavaReflection.java:63
fields.put(name, field);
} catch (NoSuchFieldException e) {
// fall through
}
parentClass = parentClass.getSuperclass();
}
}
}
return field;
}
@Override
public Object getFieldValue (Object obj, Object field) {
Field javaField = (Field)field;
try {
return javaField.get(obj);
} catch (Throwable e) {
throw new RuntimeException("Couldn't get value of field '" + javaField.getName() + "' from object of type '" + obj.getClass().getSimpleName() + "'");
}
}
@Override
public void registerExtensionClass(Class<?> target,Class<?> clazz){
Method[] methods = clazz.getDeclaredMethods();
if(methods != null){
Map<String, List<Method>> cachedMethodMap = extensionmethodCache.get(target);
if(cachedMethodMap == null){
cachedMethodMap = new HashMap<>();
extensionmethodCache.put(target,cachedMethodMap);
}
for (Method method : methods) {
if(Modifier.isStatic(method.getModifiers()) && method.getParameterCount() > 0){
List<Method> cachedList = cachedMethodMap.get(method.getName());
if(cachedList == null){
cachedList = new ArrayList<>();
cachedMethodMap.put(method.getName(), cachedList);View on GitHub (pinned to c799cca99c)