spring-projects/spring-ai · error · RuntimeException

Unsupported value type:

Error message

Unsupported value type: 

What it means

doSingleValue serializes operand values into Weaviate's GraphQL where-filter literal syntax (valueString, valueInt, valueBoolean, valueDate, ...). When a value's type has no mapping (e.g. arbitrary objects, enums, nested collections), it throws a RuntimeException 'Unsupported value type: '. Weaviate filters only support string/number/boolean/date primitives.

Solutions

  1. Coerce the value to a supported primitive (String, Number, Boolean, java.util.Date) before building the Filter.Value.
  2. Flatten complex metadata (e.g. store nested objects as separate scalar fields) and filter on the flattened fields.
  3. Add explicit conversion (e.g. enum -> name(), LocalDate -> Date) at the point where filter expressions are constructed.

Example fix

// before
var expr = new Filter.Expression(EQ, new Key("priority"), new Value(Priority.HIGH)); // enum
// after
var expr = new Filter.Expression(EQ, new Key("priority"), new Value(Priority.HIGH.name())); // String
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(v instanceof String || v instanceof Number || v instanceof Boolean || v instanceof Date)) throw new IllegalArgumentException("Unsupported Weaviate filter value type: " + v.getClass());

Type guard

static boolean isWeaviateFilterValue(Object v) { return v instanceof String || v instanceof Number || v instanceof Boolean || v instanceof Date; }

Try / catch

try { vectorStore.similaritySearch(req); } catch (RuntimeException e) { if (e.getMessage().startsWith("Unsupported value type:")) { /* coerce value to String/Number/Boolean/Date and retry */ } else throw e; }

Prevention

When it happens

Trigger: Filtering on metadata whose value is an unsupported Java type, e.g. a Map, custom POJO, enum, or array passed as a Filter.Value in a similaritySearch expression.

Common situations: Documents stored with complex metadata (nested objects, lists of objects) and filters built directly on those values; passing raw user input objects into filter values without coercion; timezone-naive or exotic date types.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

			context.append(String.format(singleValueFormat, d));
		}
		else if (value instanceof Float f) {
			context.append(String.format(singleValueFormat, f));
		}
		else if (value instanceof Boolean b) {
			context.append(String.format("valueBoolean:%s ", b));
		}
		else if (value instanceof String s) {
			context.append("valueText:");
			emitJsonValue(s, context);
			context.append(" ");
		}
		else if (value instanceof Date date) {
			String dateString = DateFormatUtils.format(date, "yyyy-MM-dd'T'HH:mm:ssZZZZZ");
			context.append(String.format("valueDate:\"%s\" ", dateString));
		}
		else {
			throw new RuntimeException("Unsupported value type: " + value);
		}
	}

	@Override
	protected void doGroup(Group group, StringBuilder context) {
		// Replaces the group: AND((foo == "bar" OR bar == "foo"), "boza" == "koza") into
		// AND(AND(id != -1, (foo == "bar" OR bar == "foo")), "boza" == "koza") into
		this.convertOperand(new Expression(ExpressionType.AND,
				new Expression(ExpressionType.NE, new Filter.Key("id"), new Filter.Value("-1")), group.content()),
				context);
	}

}

View on GitHub (pinned to 98a7beda4f)