spring-projects/spring-ai · error · IllegalStateException
Index %s does not exist in table %s
Error message
Index %s does not exist in table %s
What it means
During initialization CassandraVectorStore reads the table metadata to determine the index similarity function (cosine/euclidean/inner_product). If the configured schema index name is not found on the table it throws IllegalStateException. The store requires a pre-existing SAI index on the vector column unless it created the schema itself.
Source
Thrown at vector-stores/spring-ai-cassandra-store/src/main/java/org/springframework/ai/vectorstore/cassandra/CassandraVectorStore.java:397
.metadata(docFields)
.score((double) score)
.build();
documents.add(doc);
}
return documents;
}
void checkSchemaValid() {
this.checkSchemaValid(this.embeddingModel.dimensions());
}
private Similarity getIndexSimilarity(TableMetadata metadata) {
Optional<IndexMetadata> indexMetadata = metadata.getIndex(this.schema.index());
if (indexMetadata.isEmpty()) {
throw new IllegalStateException(
String.format("Index %s does not exist in table %s", this.schema.index(), this.schema.table));
}
return Similarity.valueOf(indexMetadata.get()
.getOptions()
.getOrDefault("similarity_function", "COSINE")
.toUpperCase(Locale.ROOT));
}
private PreparedStatement prepareDeleteStatement() {
Delete stmt = null;
DeleteSelection stmtStart = QueryBuilder.deleteFrom(this.schema.keyspace(), this.schema.table());
for (var c : this.schema.partitionKeys()) {
stmt = (null != stmt ? stmt : stmtStart).whereColumn(c.name()).isEqualTo(QueryBuilder.bindMarker(c.name()));
}
Assert.state(stmt != null, "stmt should not be null by now");View on GitHub (pinned to 98a7beda4f)
Solutions
- Verify the index name in your CassandraVectorStore schema config matches an actual SAI index: run DESC TABLE / SELECT from system_schema.indexes.
- Create the index manually if initializeSchema is false: CREATE CUSTOM INDEX IF NOT EXISTS <name> ON <ks>.<tbl>(<vector_col>) USING 'StorageAttachedIndex' WITH OPTIONS = {'similarity_function': 'COSINE'}.
- Set initializeSchema=true to let the store create the table and index itself.
- Align schema.table with the table that actually carries the index.
Example fix
// before
CassandraVectorStoreConfig.builder().keyspace("ai").table("vectors").index("vector_idx_wrong")...
// after (match the real SAI index name)
CREATE CUSTOM INDEX IF NOT EXISTS vector_idx ON ai.vectors(content_vector) USING 'StorageAttachedIndex';
CassandraVectorStoreConfig.builder().keyspace("ai").table("vectors").index("vector_idx")... Defensive patterns
Strategy: validation
Validate before calling
Optional<IndexMetadata> idx = session.getMetadata()
.getKeyspace(schema.keyspace()).flatMap(k -> k.getTable(schema.table()))
.flatMap(t -> t.getIndex(schema.index()));
if (idx.isEmpty()) throw new IllegalStateException("SAI index missing: " + schema.index()); Type guard
boolean indexExists(CqlSession s, String ks, String tbl, String idxName) {
return s.getMetadata().getKeyspace(ks).flatMap(k -> k.getTable(tbl))
.map(t -> t.getIndex(idxName).isPresent()).orElse(false);
} Try / catch
try {
new CassandraVectorStore.Builder(session, embeddingModel)
.schemaColumnFilters("vectors", "vector_idx").build();
} catch (IllegalStateException e) {
if (e.getMessage().contains("does not exist")) createSaiIndex();
} Prevention
- Create the SAI index with the exact configured name before starting the app.
- Keep index/table names in one config source shared with your schema migration scripts.
- Run DESC TABLE in the target environment to verify names when deploying to a new keyspace.
When it happens
Trigger: Constructing CassandraVectorStore with a schema whose index() name does not exist on the configured table — typo in index name, index created on a different table, or initializeSchema=false while the index was never created manually.
Common situations: Deploying against an existing Cassandra keyspace where a DBA created the SAI index with a different name; switching tables but reusing an old schema config; forgetting CREATE CUSTOM INDEX ... USING 'StorageAttachedIndex' before starting the app.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Expression type %s not yet implemented. Patches welcome.
- Failed to delete documents by filter
- Failed to initialize ChromaVectorStore
- Collection {collectionName} with the tenant: {tenantName} an
- Index not found
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/54d3be8cc4d615c5.
Report an issue: GitHub.