spring-projects/spring-ai · warning

Could not parse text search score

Error message

Could not parse text search score: ${doc.getString("$score")}

What it means

RedisVectorStore.similarityScore parses the '$score' field from the Redis search result document into a float; on NumberFormatException it warns and falls back to a default similarity of 0.9f. This means the score string was malformed or absent, and the returned Similarity value is fabricated, not measured.

Solutions

  1. Verify the index was created by RedisVectorStore so the '$score' KNN attribute is present
  2. Check the actual '$score' value in Redis (FT.SEARCH output) for malformed content
  3. Upgrade spring-ai-redis-store / RediSearch to a version returning parseable numeric scores
  4. Treat results with default 0.9 score with suspicion; re-run the query after fixing the index

Example fix

// before
// score field missing -> silently 0.9
List<Document> docs = vectorStore.similaritySearch(query);

// after
// recreate index via RedisVectorStore#afterPropertiesSet or check FT.INFO index
// ensure KNN query includes return field "$score"
Defensive patterns

Strategy: type-guard

Validate before calling

String score = doc.getString("$score");
if (score == null || !score.matches("-?\\d+(\\.\\d+)?")) {
    logger.warn("'$score' missing or non-numeric: " + score);
}

Type guard

boolean hasNumericScore(Document doc) {
    String s = doc.getMetadata().get("$score", "");
    try { Float.parseFloat(s); return true; } catch (Exception e) { return false; }
}

Try / catch

try {
    List<Document> docs = redisVectorStore.similaritySearch(req);
    docs.stream().filter(d -> !hasNumericScore(d)).forEach(d -> logger.warn("fabricated 0.9 score for " + d.getId()));
} catch (RuntimeException e) {
    logger.error("Redis similarity search failed", e);
}

Prevention

When it happens

Trigger: Executing similaritySearch where the KNN '$score' attribute in the Redis reply cannot be parsed as a float — e.g. score field missing/empty, a non-numeric string, or locale/format issues.

Common situations: Custom Redis indexes missing the score attribute; mixing index definitions; Redis module (RediSearch) versions returning scores in unexpected format; queries executed against an index not created by the store.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at vector-stores/spring-ai-redis-store/src/main/java/org/springframework/ai/vectorstore/redis/RedisVectorStore.java:562

			try {
				// Text search scores can be very high (like 10.0), normalize to 0.0-1.0
				// range
				float textScore = Float.parseFloat(doc.getString("$score"));
				// A simple normalization strategy - text scores are usually positive,
				// scale to 0.0-1.0
				// Assuming 10.0 is a "perfect" score, but capping at 1.0
				float normalizedTextScore = Math.min(textScore / 10.0f, 1.0f);

				if (logger.isDebugEnabled()) {
					logger.debug("Text search raw score: " + textScore + ", normalized: " + normalizedTextScore);
				}

				return normalizedTextScore;
			}
			catch (NumberFormatException e) {
				// If we can't parse the score, fall back to default
				if (logger.isWarnEnabled()) {
					logger.warn("Could not parse text search score: " + doc.getString("$score"));
				}
				return 0.9f; // Default high similarity
			}
		}

		// Handle the case where the distance field might not be present (like in text
		// search)
		if (!doc.hasProperty(DISTANCE_FIELD_NAME)) {
			// For text search, we don't have a vector distance, so use a default high
			// similarity
			logger.debug("No vector distance score found. Using default similarity.");
			return 0.9f; // Default high similarity
		}

		float rawScore = Float.parseFloat(doc.getString(DISTANCE_FIELD_NAME));

		// Different distance metrics need different score transformations
		if (logger.isDebugEnabled()) {

View on GitHub (pinned to 98a7beda4f)