spring-projects/spring-ai · error · RuntimeException

Not supported expression type:

Error message

Not supported expression type: 

What it means

Neo4jVectorFilterExpressionConverter.getOperationSymbol switches over Filter.ExpressionType and throws a RuntimeException for any type it has no Cypher operator mapping for (default branch). This means a filter expression containing an expression type the Neo4j converter does not support was passed to the store for a similarity search with a filter.

Solutions

  1. Rewrite the filter expression using only supported types (AND, OR, EQ, NE, LT, LTE, GT, GTE, IN, NOT, NIN).
  2. Replace NIN with a negated IN via NOT to keep within supported symbols.
  3. Check the Spring AI version; upgrade or downgrade so converter and Filter.ExpressionType are in sync.
  4. Contribute/implement the missing case in getOperationSymbol if a new expression type is needed.

Example fix

// before
new Filter.Expression(ExpressionType.NOT, new In("tag", List.of("x")), null); // unhandled combination
// after
new Filter.Nin("tag", List.of("x")); // maps to the supported " NOT " symbol
Defensive patterns

Strategy: validation

Validate before calling

static boolean isSupported(Filter.Expression exp) {
    return switch (exp.type()) {
        case AND, OR, EQ, NE, LT, LTE, GT, GTE, IN, NOT, NIN -> true;
        default -> false;
    };
}
// check recursively before similaritySearch

Try / catch

try {
    vectorStore.similaritySearch(request);
} catch (RuntimeException e) {
    if (e.getMessage().startsWith("Not supported expression type")) {
        // fall back to unfiltered search and post-filter
    }
}

Prevention

When it happens

Trigger: Passing a SearchRequest whose filter expression uses an ExpressionType not mapped in the switch (e.g. NIN combined semantics, or a new type added to Filter in a newer Spring AI version) to Neo4jVectorStore.similaritySearch.

Common situations: Building complex filters programmatically with NOT/NIN and hitting an unhandled branch; upgrading Spring AI where new ExpressionType values were added but this converter was not updated; hand-rolled Filter.Expression trees containing unsupported nodes.

Related errors


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

Appendix: source

Thrown at vector-stores/spring-ai-neo4j-store/src/main/java/org/springframework/ai/vectorstore/neo4j/filter/Neo4jVectorFilterExpressionConverter.java:64

			context.append(this.getOperationSymbol(expression));
			this.convertOperand(expression.right(), context);
		}
	}

	private String getOperationSymbol(Expression exp) {
		return switch (exp.type()) {
			case AND -> " AND ";
			case OR -> " OR ";
			case EQ -> " = ";
			case NE -> " <> ";
			case LT -> " < ";
			case LTE -> " <= ";
			case GT -> " > ";
			case GTE -> " >= ";
			case IN -> " IN ";
			case NOT, NIN -> " NOT ";
			// you never know what the future might bring
			default -> throw new RuntimeException("Not supported expression type: " + exp.type());
		};
	}

	@Override
	protected void doNot(Expression expression, StringBuilder context) {
		Filter.ExpressionType expressionType = expression.type();
		// should not happen, but better safe than sorry
		if (expressionType != Filter.ExpressionType.NOT) {
			throw new RuntimeException(
					"Unsupported expression type %s. Only NOT is supported here".formatted(expressionType));
		}

		// explicitly prefix the embedded expression with NOT
		context.append("NOT ").append(this.convertOperand(expression.left()));
	}

	@Override
	protected void doKey(Key key, StringBuilder context) {

View on GitHub (pinned to 98a7beda4f)