spring-projects/spring-ai · error · IllegalArgumentException

<joined GraphQL error messages>

Error message

<joined GraphQL error messages>

What it means

Even when the HTTP-level Result has no errors, the GraphQL response body can carry GraphQLError[] entries (application-level GraphQL errors). doSimilaritySearch joins their messages and throws IllegalArgumentException. This distinguishes protocol success from query-level failure.

Solutions

  1. Read the joined GraphQL error messages in the exception — they pinpoint the invalid field/argument.
  2. Validate the where-filter structure: property names must exist in the Weaviate class with matching value types.
  3. Test the generated query in a GraphQL IDE against the live schema to confirm field names.
  4. Update the spring-ai-weaviate-store module if the server schema introduced newer GraphQL features the client emits incorrectly.

Example fix

// before
FilterExpressionBuilder b = new FilterExpressionBuilder();
// searching on metadata field 'age' stored as string but filtered as number -> GraphQL error
// after
// declare MetadataField with the type matching the Weaviate schema property:
new WeaviateVectorStore.builder(client, embeddingModel)
    .filterMetadataFields(List.of(new MetadataField("age", MetadataField.MetadataFieldType.NUMBER)))
    .build();
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure filter fields exist with matching types
Set<String> props = schema.getClass(objectClass).getProperties().stream().map(p -> p.getName()).collect(toSet());
filterFields.forEach(f -> { if (!props.contains(f.name())) throw new IllegalStateException("Unknown filter field: " + f.name()); });

Try / catch

try { vectorStore.similaritySearch(req); } catch (IllegalArgumentException e) { /* message contains joined GraphQLError messages naming the invalid field */ }

Prevention

When it happens

Trigger: VectorStore.similaritySearch(SearchRequest) where result.getResult().getErrors() is non-empty — e.g. GraphQL validation errors (unknown field/argument), where-filter type errors, or partial resolver failures reported in the 200 response body.

Common situations: Using Filter operators unsupported by the Weaviate where-filter grammar; mismatch between filterMetadataFields types and schema property types (string vs int); querying nearVector on a class without a vectorizer configured.

Related errors


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

Appendix: source

Thrown at vector-stores/spring-ai-weaviate-store/src/main/java/org/springframework/ai/vectorstore/weaviate/WeaviateVectorStore.java:370

		}
		else {
			// remove the empty 'where:{}' placeholder.
			graphQLQuery = graphQLQuery.replace("where:{}", "");
		}

		Result<GraphQLResponse> result = this.weaviateClient.graphQL().raw().withQuery(graphQLQuery).run();

		if (result.hasErrors()) {
			throw new IllegalArgumentException(result.getError()
				.getMessages()
				.stream()
				.map(WeaviateErrorMessage::getMessage)
				.collect(Collectors.joining(System.lineSeparator())));
		}

		GraphQLError[] errors = result.getResult().getErrors();
		if (errors != null && errors.length > 0) {
			throw new IllegalArgumentException(Arrays.stream(errors)
				.map(GraphQLError::getMessage)
				.collect(Collectors.joining(System.lineSeparator())));
		}

		@SuppressWarnings("unchecked")
		Optional<Map.Entry<String, Map<?, ?>>> resGetPart = ((Map<String, Map<?, ?>>) result.getResult().getData())
			.entrySet()
			.stream()
			.findFirst();
		if (!resGetPart.isPresent()) {
			return List.of();
		}

		Optional<?> resItemsPart = resGetPart.get().getValue().entrySet().stream().findFirst();
		if (!resItemsPart.isPresent()) {
			return List.of();
		}

View on GitHub (pinned to 98a7beda4f)