spring-projects/spring-ai · error · RuntimeException
Failed to extract record field types
Error message
Failed to extract record field types
What it means
ToolInputSchemaAugmenter.toAugmentedArgumentTypes() reflects over a record's components to derive augmented argument types (name, type, description, required). Any exception during that reflective extraction (e.g. the argumentType is not a record, access errors) is wrapped in a RuntimeException with this message and the original cause attached.
Source
Thrown at spring-ai-model/src/main/java/org/springframework/ai/tool/augment/ToolInputSchemaAugmenter.java:73
// Get the annotation from the corresponding field, not the record
// component
ToolParam toolParam = null;
try {
var field = recordClass.getDeclaredField(c.getName());
toolParam = field.getAnnotation(ToolParam.class);
}
catch (NoSuchFieldException e) {
// Field not found, toolParam remains null
}
return new AugmentedArgumentType(c.getName(), c.getGenericType(),
toolParam != null ? toolParam.description() : "no description",
toolParam != null ? toolParam.required() : false);
}).toList();
}
catch (Exception e) {
throw new RuntimeException("Failed to extract record field types", e);
}
}
public static String augmentToolInputSchema(String jsonSchemaString, String propertyName, Type propertyType,
String description, boolean required) {
return augmentToolInputSchema(jsonSchemaString,
List.of(new AugmentedArgumentType(propertyName, propertyType, description, required)));
}
public static String augmentToolInputSchema(String jsonSchemaString, List<AugmentedArgumentType> argumentType) {
try {
ObjectNode schemaObjectNode = (ObjectNode) JacksonUtils.getDefaultJsonMapper().readTree(jsonSchemaString);
// Handle properties
ObjectNode propertiesNode;View on GitHub (pinned to 98a7beda4f)
Solutions
- Ensure argumentType is a Java record: convert the POJO to a record with matching components.
- Inspect the wrapped cause (e.getCause()) for the exact reflective failure.
- Annotate record components with @ToolParam(description=..., required=...) so extraction completes cleanly.
Example fix
// before
builder().argumentType(UserArgsPojo.class) // not a record
// after
public record UserArgs(@ToolParam(description = "User id", required = true) String userId) {}
builder().argumentType(UserArgs.class) Defensive patterns
Strategy: validation
Validate before calling
if (argumentType == null || !argumentType.isRecord()) {
throw new IllegalArgumentException("argumentType must be a Java record, got: " + argumentType);
} Type guard
static boolean isRecordType(Class<?> c) { return c != null && c.isRecord(); } Try / catch
try { provider = builder.build(); } catch (RuntimeException e) { if (e.getMessage().contains("Failed to extract record field types")) throw new IllegalArgumentException("argumentType must be a record", e); throw e; } Prevention
- Define tool argument types exclusively as Java records with @ToolParam annotations.
- Add a unit test that builds the provider for every registered tool argument type.
When it happens
Trigger: Passing a non-record class (plain POJO, interface, String, etc.) as argumentType to AugmentedToolCallbackProvider or toAugmentedArgumentTypes; a record type whose component accessors cannot be reflectively read.
Common situations: Upgrading from POJO-based tool arguments to the record requirement in newer Spring AI; accidentally passing the tool's return type or a generic Map instead of the request record.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Failed to parse JSON schema
- ClassNotFoundException (wrapped RuntimeException)
- Could not access method:
- Failed to instantiate ToolCallResultConverter:
- Neither createIndex() nor ensureIndex() method found on Inde
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/f97aa86ed460b985.
Report an issue: GitHub.