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

  1. Set CASSANDRA_ENSURE_SCHEMA=true to let Zipkin apply the missing index/schema upgrade, then optionally turn it back off.
  2. Or manually apply the referenced upgrade/index cql file named in the error message.
  3. 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

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


AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14). Data as JSON: /api/errors/cfaecb310f537773. Report an issue: GitHub.