spring-projects/spring-ai · error · UnsupportedOperationException

Cassandra uses a custom doValue(ColumnMetadata, Object, Stri

Error message

Cassandra uses a custom doValue(ColumnMetadata, Object, StringBuilder) implementation that leverages CodecRegistry.DEFAULT.codecFor(dataType).format(v). This method should not be called.

What it means

CassandraFilterExpressionConverter overrides doValue(ColumnMetadata, Object, StringBuilder) and formats values via CodecRegistry codecs based on the column's CQL data type. The generic doSingleValue hook is therefore intentionally disabled and always throws UnsupportedOperationException to catch incorrect dispatch paths.

Source

Thrown at vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/cassandra/CassandraFilterExpressionConverter.java:166

				name = name.substring(1, name.length() - 1);
				column = Optional.ofNullable(this.columnsByName.get(name));
			}
		}
		return column;
	}

	/**
	 * Cassandra uses a custom value formatting approach via
	 * {@link #doValue(ColumnMetadata, Object, StringBuilder)} that leverages the driver's
	 * CodecRegistry. This method is not used in the normal flow and will throw an
	 * exception if called.
	 * @param value the value to convert
	 * @param context the context to append the string representation to
	 * @throws UnsupportedOperationException always, as this method should not be called
	 */
	@Override
	protected void doSingleValue(Object value, StringBuilder context) {
		throw new UnsupportedOperationException(
				"Cassandra uses a custom doValue(ColumnMetadata, Object, StringBuilder) implementation "
						+ "that leverages CodecRegistry.DEFAULT.codecFor(dataType).format(v). "
						+ "This method should not be called.");
	}

}

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Ensure values are converted through doValue(ColumnMetadata, Object, StringBuilder), which uses CodecRegistry.DEFAULT.codecFor(dataType).format(v).
  2. If extending the converter, override doValue instead of calling doSingleValue.
  3. If this fires from library internals after an upgrade, pin to a compatible Spring AI version or file an issue.

Example fix

// before (custom subclass calling the generic hook)
protected void doValue(Object v, StringBuilder ctx) { doSingleValue(v, ctx); }
// after
protected void doValue(ColumnMetadata col, Object v, StringBuilder ctx) {
  ctx.append(CodecRegistry.DEFAULT.codecFor(col.getType()).format(v));
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Ensure the store/converter in use is CassandraFilterExpressionConverter, not the base class
if (!(converter instanceof CassandraFilterExpressionConverter c)) {
  throw new IllegalStateException("Cassandra store requires its own filter converter");
}

Type guard

boolean usesCassandraConverter(FilterVectorExpressionConverter c) {
  return c instanceof CassandraFilterExpressionConverter;
}

Try / catch

try {
  converter.convertExpression(filter);
} catch (UnsupportedOperationException e) {
  throw new IllegalStateException("Converter must use Cassandra doValue(ColumnMetadata,...) path", e);
}

Prevention

When it happens

Trigger: A code path or subclass (or framework upgrade changing FilterVectorExpressionConverter internals) that invokes doSingleValue directly instead of the Cassandra-specific doValue overload; custom subclasses that bypass the Cassandra column-aware conversion.

Common situations: Upgrading Spring AI where the base class converter starts calling doSingleValue for some expression types; writing a custom converter subclass that reuses doSingleValue.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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