spring-projects/spring-ai · error · RuntimeException

Bad Request

Error message

Bad Request: %s

What it means

GemFireVectorStore.handleHttpClientException maps a WebClientResponseException with HTTP 400 BAD_REQUEST to RuntimeException("Bad Request: %s"). The server rejected the request payload or parameters sent to the GemFire REST API as malformed or invalid.

Solutions

  1. Inspect the chained exception message for the server's 400 detail
  2. Validate request parameters (k, threshold, filter expressions) produce valid GemFire OQL/payloads
  3. Confirm embedding dimensions match the index configuration
  4. Check the GemFire REST API version/path expected by your server release

Example fix

// before: unescaped quote breaks the server-side query
new Filter.Expression(ExpressionType.EQ, new MetadataKey("title"), new MetadataValue("it's here"));
// after: sanitize metadata values before storing/querying
new Filter.Expression(ExpressionType.EQ, new MetadataKey("title"), new MetadataValue("its here"));
Defensive patterns

Strategy: try-catch

Validate before calling

Objects.requireNonNull(k, "k must not be null");
Assert.isTrue(k > 0 && k <= 1000, "k out of range");
// also sanitize metadata values of OQL-special characters

Try / catch

try {
    vectorStore.similaritySearch(SearchRequest.builder().query(q).topK(k).build());
} catch (RuntimeException e) {
    if (e.getMessage().startsWith("Bad Request")) {
        logger.error("GemFire rejected request: {}", e.getMessage(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Any GemFire vector store operation whose REST request the server answers with 400: malformed query parameters (e.g. invalid limit/k, bad OQL produced by a filter), or an invalid JSON body in put/create-index calls.

Common situations: Illegal characters or OQL syntax in filter values, embedding dimension mismatch producing an invalid request body, wrong API path/version for the GemFire server, or overly large payloads.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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

Appendix: source

Thrown at vector-stores/spring-ai-gemfire-store/src/main/java/org/springframework/ai/vectorstore/gemfire/GemFireVectorStore.java:344

			.block();
	}

	/**
	 * Handles exceptions that occur during HTTP client operations and maps them to
	 * appropriate runtime exceptions.
	 * @param ex the exception that occurred during HTTP client operation
	 * @return a mapped runtime exception corresponding to the HTTP client exception
	 */
	private Throwable handleHttpClientException(Throwable ex) {
		if (!(ex instanceof WebClientResponseException clientException)) {
			throw new RuntimeException(String.format("Got an unexpected error: %s", ex));
		}

		if (clientException.getStatusCode().equals(org.springframework.http.HttpStatus.NOT_FOUND)) {
			throw new RuntimeException(String.format("Index %s not found: %s", this.indexName, ex));
		}
		else if (clientException.getStatusCode().equals(org.springframework.http.HttpStatus.BAD_REQUEST)) {
			throw new RuntimeException(String.format("Bad Request: %s", ex));
		}
		else {
			throw new RuntimeException(String.format("Got an unexpected HTTP error: %s", ex));
		}
	}

	@Override
	public VectorStoreObservationContext.Builder createObservationContextBuilder(String operationName) {
		return VectorStoreObservationContext.builder(VectorStoreProvider.GEMFIRE.value(), operationName)
			.collectionName(this.indexName)
			.dimensions(this.embeddingModel.dimensions())
			.fieldName(EMBEDDINGS);
	}

	public static class CreateRequest {

		@JsonProperty("name")
		private final String indexName;

View on GitHub (pinned to 98a7beda4f)