spring-projects/spring-ai · error · IllegalStateException

Failed to delete documents by filter

Error message

Failed to delete documents by filter

What it means

MariaDBVectorStore.doDelete builds a DELETE statement with a filter expression and executes it via JdbcTemplate. Any exception during SQL construction or execution is caught, logged, and rethrown as an IllegalStateException('Failed to delete documents by filter', cause). The original cause is preserved as the root exception.

Source

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

	protected void doDelete(Filter.Expression filterExpression) {
		Assert.notNull(filterExpression, "Filter expression must not be null");

		try {
			String nativeFilterExpression = this.filterExpressionConverter.convertExpression(filterExpression);

			String sql = String.format("DELETE FROM %s WHERE %s", getFullyQualifiedTableName(), nativeFilterExpression);

			if (logger.isDebugEnabled()) {
				logger.debug("Executing delete with filter: " + sql);
			}

			this.jdbcTemplate.update(sql);
		}
		catch (Exception e) {
			if (logger.isErrorEnabled()) {
				logger.error("Failed to delete documents by filter: " + e.getMessage(), e);
			}
			throw new IllegalStateException("Failed to delete documents by filter", e);
		}
	}

	@Override
	public List<Document> doSimilaritySearch(SearchRequest request) {

		String nativeFilterExpression = (request.getFilterExpression() != null)
				? this.filterExpressionConverter.convertExpression(request.getFilterExpression()) : "";
		float[] embedding = this.embeddingModel.embed(request.getQuery());
		String jsonPathFilter = "";

		if (StringUtils.hasText(nativeFilterExpression)) {
			jsonPathFilter = "and " + nativeFilterExpression + " ";
		}
		String distanceType = this.distanceType.name().toLowerCase(Locale.ROOT);

		double distance = 1 - request.getSimilarityThreshold();
		final String sql = String.format(

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Inspect the chained cause (e.getCause()) for the underlying SQLException and fix that first.
  2. Simplify or correct the FilterExpression to operators the MariaDB converter supports.
  3. Verify the table schema matches the expected columns via MariaDBSchemaValidator.
  4. Check database connectivity and retry the delete.

Example fix

// before
vectorStore.delete("year > 2020 and genre nin ['news']"); // assume NOT/NIN support
// after
vectorStore.delete(new FilterExpressionBuilder().gt("year", 2020).build());
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate filter is translatable and table exists before deleting:
Integer n = jdbc.queryForObject(
    "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=?",
    Integer.class, tableName);
if (n == null || n == 0) throw new IllegalStateException("Table missing: " + tableName);

Try / catch

try {
    vectorStore.delete(filterExpression);
} catch (IllegalStateException e) {
    Throwable root = e.getCause();
    logger.error("delete failed: {}", root == null ? e : root.getMessage(), root);
    // rollback/compensate or retry after fixing the SQL-level cause
}

Prevention

When it happens

Trigger: Calling vectorStore.delete(filterExpression) when the generated SQL is invalid (unsupported filter expression type, bad identifier), the connection fails, or the table/columns are missing — any SQLException or DataAccessException from jdbcTemplate.update.

Common situations: Complex FilterExpressions translated to invalid MariaDB SQL, JSON_VALUE-based metadata filters failing on malformed metadata, DB connection drops mid-transaction, table schema drift after upgrades.

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


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