openzipkin/zipkin · critical · RuntimeException
schema lacks indexing: apply %s, or set CASSANDRA_ENSURE_SCH
Error message
schema lacks indexing: apply %s, or set CASSANDRA_ENSURE_SCHEMA=true
What it means
Schema validation throws a RuntimeException with 'schema lacks indexing: apply %s, or set CASSANDRA_ENSURE_SCHEMA=true' when the keyspace exists but is missing the search/index tables (e.g. span_annotations with indexing) that Zipkin requires for query support. Like the other schema errors it is logged at ERROR then rethrown.
Source
Thrown at zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/Schema.java:96
"schema lacks autocomplete indexing: apply {}, or set CASSANDRA_ENSURE_SCHEMA=true",
UPGRADE_1);
}
if (!hasRemoteService) {
LOG.warn(
"schema lacks remote service indexing: apply {}, or set CASSANDRA_ENSURE_SCHEMA=true",
UPGRADE_2);
}
return md;
}
static void logAndThrow(String messageFormat, Object... args) {
String message = messageFormat.formatted(args);
// Ensure we can look at logs to see the problem. Otherwise, it may only
// be visible in API error responses, such as /health or /api/v2/traces.
LOG.error(message);
throw new RuntimeException(message);
}
static void initializeUDTs(CqlSession session, String keyspace) {
KeyspaceMetadata ks = session.getMetadata().getKeyspace(keyspace).get();
MutableCodecRegistry codecRegistry =
(MutableCodecRegistry) session.getContext().getCodecRegistry();
TypeCodec<UdtValue> annotationUDTCodec =
codecRegistry.codecFor(ks.getUserDefinedType("annotation").get());
codecRegistry.register(new AnnotationCodec(annotationUDTCodec));
LOG.debug("Registering endpoint and annotation UDTs to keyspace {}", keyspace);
TypeCodec<UdtValue> endpointUDTCodec =
codecRegistry.codecFor(ks.getUserDefinedType("endpoint").get());
codecRegistry.register(new EndpointCodec(endpointUDTCodec));
}
static final class Metadata {View on GitHub (pinned to 878ce2a1fa)
Solutions
- Set CASSANDRA_ENSURE_SCHEMA=true to let Zipkin apply the missing index/schema upgrade, then optionally turn it back off.
- Or manually apply the referenced upgrade/index cql file named in the error message.
- Re-run schema validation (e.g. hit /health) after applying to confirm the keyspace passes.
Example fix
// before CASSANDRA_ENSURE_SCHEMA=false // after (one-time, then revert) CASSANDRA_ENSURE_SCHEMA=true
Defensive patterns
Strategy: validation
Validate before calling
// Verify index/search tables exist before locking ensureSchema=false
KeyspaceMetadata ks = session.getMetadata().getKeyspace(keyspace).orElseThrow();
boolean hasIndexes = ks.getTable("span_annotations").isPresent() && ks.getTable("remote_service_names").isPresent();
if (!hasIndexes) throw new IllegalStateException("Apply index schema/upgrade first"); Try / catch
catch (RuntimeException e) { if (e.getMessage() != null && e.getMessage().contains("schema lacks")) { runOneTimeEnsureSchema(); } else throw e; } Prevention
- After every Zipkin upgrade, run one boot with CASSANDRA_ENSURE_SCHEMA=true, verify /health, then disable it.
- Track applied schema versions per environment like a migration changelog.
When it happens
Trigger: An old Zipkin schema version was installed before index tables existed, and ensureSchema=false so validation catches the gap; search indexes were only conditionally installed (searchEnabled) but queries are enabled.
Common situations: Upgrading Zipkin against a long-lived Cassandra keyspace; a cluster where someone applied only the base schema cql and not the index cql.
Related errors
- {annotationQueryString} query unsupported due to missing ann
- remoteService={remoteService} unsupported due to missing tab
- Session initialization failed. See server logs
- schema not installed: apply %s, or set CASSANDRA_ENSURE_SCHE
- Failed to execute [%s]: %s
AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14).
Data as JSON: /api/errors/cfaecb310f537773.
Report an issue: GitHub.