spring-projects/spring-framework · error · IllegalStateException

Could not find original class structure

Error message

Could not find original class structure

What it means

Thrown as an IllegalStateException during deserialization of a DependencyDescriptor: readObject restores the reflective Field/MethodParameter handles from the stored declaring class and member name; if the class no longer has that field/method/constructor (renamed, removed, signature changed, class missing), the reflective lookup throws and is wrapped with this message.

Solutions

  1. Ensure both producer and consumer of the serialized descriptor run the same application/class versions so the member still exists.
  2. Avoid serializing DependencyDescriptor across version boundaries; pass plain bean names/types and re-resolve on the receiving side.
  3. If you control the injection point, keep the field/method name and signature stable across versions, or invalidate caches after refactors.
  4. Invalidate or migrate any persistent cache holding serialized descriptors when the class structure changes.
  5. Inspect the 'caused by' (NoSuchFieldException / NoSuchMethodException) to find which member is missing, then restore or rename it back.

Example fix

// before: serializing a DependencyDescriptor across versions
// node A (v1): field 'orderRepo'  -> node B (v2): field renamed 'repository'
ObjectOutputStream oos = ...;
oos.writeObject(dependencyDescriptor);

// after: don't ship the descriptor; ship the bean name and re-resolve
oos.writeObject(descriptor.getDependencyType());
oos.writeObject(beanName);
// receiver: beanFactory.getBean(beanName, type);
Defensive patterns

Strategy: validation

Validate before calling

// Verify the reflective member still exists before deserializing/using
Class<?> c = descriptor.getDeclaringClass();
if (descriptor.getFieldName() != null) {
    c.getDeclaredField(descriptor.getFieldName()); // throws if missing
}

Prevention

When it happens

Trigger: Deserializing a DependencyDescriptor (across an RPC boundary, in a session, or cached) on a JVM where the declaring class's structure does not match what was serialized: getDeclaredField/getDeclaredMethod/getDeclaredConstructor fails. Triggered inside readObject when reconstructing this.field or this.methodParameter.

Common situations: Distributing a DependencyDescriptor between nodes running different versions of the application where a field/method was renamed or deleted; serializing a descriptor that points at a class that was later removed; refactoring an @Autowired field's name after a descriptor was cached; classloader differences hiding the expected member; cross-major Spring upgrade that changed reflective metadata.

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/3f79df64b06afa3f. Report an issue: GitHub.

Appendix: source

Thrown at spring-beans/src/main/java/org/springframework/beans/factory/config/DependencyDescriptor.java:434

			if (this.fieldName != null) {
				this.field = this.declaringClass.getDeclaredField(this.fieldName);
			}
			else {
				if (this.methodName != null) {
					this.methodParameter = new MethodParameter(
							this.declaringClass.getDeclaredMethod(this.methodName, this.parameterTypes), this.parameterIndex);
				}
				else {
					this.methodParameter = new MethodParameter(
							this.declaringClass.getDeclaredConstructor(this.parameterTypes), this.parameterIndex);
				}
				for (int i = 1; i < this.nestingLevel; i++) {
					this.methodParameter = this.methodParameter.nested();
				}
			}
		}
		catch (Throwable ex) {
			throw new IllegalStateException("Could not find original class structure", ex);
		}
	}

}

View on GitHub (pinned to 69bf83ad71)