jaegertracing/jaeger · critical

neither table %s nor %s exist

Error message

neither table %s nor %s exist

What it means

NewOperationNamesStorage checks which schema version of the operation-names table exists in the Cassandra keyspace. It prefers the latest table but falls back to the previous version; if neither table exists it refuses to start, because it cannot answer operation-name queries against an empty/unschema'd keyspace.

Source

Thrown at internal/storage/v1/cassandra/spanstore/operation_names.go:99

	table          tableMeta
	session        cassandra.Session
	writeCacheTTL  time.Duration
	metrics        *casmetrics.Table
	operationNames cache.Cache
	logger         *zap.Logger
}

// NewOperationNamesStorage returns a new OperationNamesStorage
func NewOperationNamesStorage(
	session cassandra.Session,
	writeCacheTTL time.Duration,
	metricsFactory metrics.Factory,
	logger *zap.Logger,
) (*OperationNamesStorage, error) {
	schemaVersion := latestVersion
	if !tableExist(session, schemas[schemaVersion].tableName) {
		if !tableExist(session, schemas[previousVersion].tableName) {
			return nil, fmt.Errorf("neither table %s nor %s exist",
				schemas[schemaVersion].tableName, schemas[previousVersion].tableName)
		}
		schemaVersion = previousVersion
	}
	table := schemas[schemaVersion]
	table.materialize()

	return &OperationNamesStorage{
		session:       session,
		schemaVersion: schemaVersion,
		table:         table,
		metrics:       casmetrics.NewTable(metricsFactory, schemas[schemaVersion].tableName),
		writeCacheTTL: writeCacheTTL,
		logger:        logger,
		operationNames: cache.NewLRUWithOptions(
			100000,
			&cache.Options{
				TTL:             writeCacheTTL,

View on GitHub (pinned to 806f444784)

Solutions

  1. Run the Jaeger Cassandra schema initializer against the configured keyspace (jaeger-cassandra-schema image or plugin/schema/cassandra.cql) to create the tables.
  2. Verify you are connected to the intended keyspace (CASSANDRA_KEYSPACE / keyspace config) — a typo lands you in an empty keyspace.
  3. Check that the schema init job completed: inspect system_schema.tables for operation_names_v2 (or operation_names).
  4. If you intentionally run an older schema, create at least the v1 operation_names table so the fallback path works.

Example fix

// before
session, _ := cluster.CreateSession() // keyspace "jaeger_v1" exists but is empty
reader, err := spanstore.NewSpanReader(session, ...) // errors
// after
// cqlsh: CREATE TABLE jaeger_v1.operation_names_v2 (service_name text, bucket int, operation_name text, span_kind text, PRIMARY KEY ((service_name), operation_name, span_kind));
reader, err := spanstore.NewSpanReader(session, ...) // succeeds
Defensive patterns

Strategy: validation

Validate before calling

iter := session.Query("SELECT table_name FROM system_schema.tables WHERE keyspace_name = ?", keyspace).Iter()
var tables []string
var t string
for iter.Scan(&t) {
    tables = append(tables, t)
}
// require operation_names_v2 or operation_names before constructing storage

Try / catch

writer, err := spanstore.NewSpanWriter(session, metrics, logger, cfg)
if err != nil {
    if strings.Contains(err.Error(), "neither table") {
        // run schema initialization then retry startup
    }
    return err
}

Prevention

When it happens

Trigger: Calling NewSpanReader/NewSpanWriter (or withOperationNamesStorage) against a Cassandra keyspace that lacks both the v2 (operation_names_v2, with span_kind) and v1 (operation_names) tables.

Common situations: Pointing Jaeger at a fresh keyspace without running the schema creation script (cassandra-schema.cql / docker run jaeger-tracing-schema tool); connecting to the wrong keyspace; a schema init job that failed silently; manual table drops.

Related errors


AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01). Data as JSON: /api/errors/b4a082a4906ebefa. Report an issue: GitHub.