spring-projects/spring-ai · error · IllegalArgumentException

instantiation failed

Error message

 instantiation failed

What it means

MetaUtils.getMeta reflectively invokes the no-arg constructor of a MetaProvider via Constructor.newInstance(). This error wraps InvocationTargetException, InstantiationException, or IllegalAccessException when instantiation or the constructor body fails — e.g. the constructor threw an exception, the class is abstract, or the constructor is not accessible.

Solutions

  1. Read the wrapped cause (e.getCause()) to find the real failure inside the constructor and fix it
  2. Ensure the registered class is a concrete, instantiable class, not abstract or an interface
  3. Make the no-arg constructor public
  4. Remove heavy/fragile initialization from the constructor; do it lazily in getMeta()

Example fix

// before
class MyMetaProvider implements MetaProvider {
    MyMetaProvider() { connectToRemote(); } // throws at construction
}

// after
class MyMetaProvider implements MetaProvider {
    public Map<String, Object> getMeta() {
        return Map.of("status", lookupStatus()); // no throwing ctor work
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// instantiate eagerly at startup to fail fast
Object probe = metaProviderClass.getDeclaredConstructor().newInstance();

Try / catch

try {
    Map<String, Object> meta = MetaUtils.getMeta(providerClass);
} catch (IllegalArgumentException e) {
    Throwable cause = e.getCause();
    log.error("MetaProvider {} failed: {}", providerClass.getName(),
        cause != null ? cause.getMessage() : e.getMessage(), cause);
}

Prevention

When it happens

Trigger: A MetaProvider no-arg constructor that throws (wrapping InvocationTargetException); the registered class is abstract or an interface (InstantiationException); the constructor exists but is not public and not accessible (IllegalAccessException).

Common situations: Constructor initialization logic fails at runtime (missing env vars, failed connections); someone registers an interface or abstract base class as the provider; provider class is package-private and the module system blocks reflective access.

Related errors


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/c43dedf2f5ef206d. Report an issue: GitHub.

Appendix: source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/common/MetaUtils.java:82

	public static Map<String, Object> getMeta(Class<? extends MetaProvider> metaProviderClass) {

		if (metaProviderClass == null) {
			return null;
		}

		String className = metaProviderClass.getName();
		MetaProvider metaProvider;
		try {
			// Prefer a public no-arg constructor; fall back to a declared no-arg if
			// accessible
			Constructor<? extends MetaProvider> constructor = getConstructor(metaProviderClass);
			metaProvider = constructor.newInstance();
		}
		catch (NoSuchMethodException e) {
			throw new IllegalArgumentException("Required no-arg constructor not found in " + className, e);
		}
		catch (InvocationTargetException | InstantiationException | IllegalAccessException e) {
			throw new IllegalArgumentException(className + " instantiation failed", e);
		}

		Map<String, Object> meta = metaProvider.getMeta();
		return meta == null ? null : Collections.unmodifiableMap(meta);
	}

	/**
	 * Locate a no-argument constructor on the given class: prefer public, otherwise fall
	 * back to a declared no-arg constructor.
	 * @param metaProviderClass the class to inspect
	 * @return the resolved no-arg constructor
	 * @throws NoSuchMethodException if the class does not declare any no-arg constructor
	 */
	private static Constructor<? extends MetaProvider> getConstructor(Class<? extends MetaProvider> metaProviderClass)
			throws NoSuchMethodException {
		try {
			return metaProviderClass.getDeclaredConstructor();
		}

View on GitHub (pinned to 98a7beda4f)