temporalio/temporal · critical

unable to initialize metadata manager

Error message

unable to initialize metadata manager: %w

What it means

Wraps the error from factory.NewMetadataManager() while bootstrapping system namespaces. The metadata manager is the persistence component that reads/writes namespaces; constructing it validates the underlying data store (SQL/Cassandra) and schema. If the datastore is unreachable, credentials are wrong, or the metadata tables/schema version are missing or incompatible, this error is returned and server startup aborts.

Solutions

  1. Read the wrapped cause for the concrete DB error (connection refused, access denied, table not found)
  2. Apply/upgrade the persistence schema: temporal-sql-tool setup + update-schema for your plugin and version
  3. Verify persistence config in your config yaml: plugin, host, port, credentials, database name, and that the DB is reachable (try connecting with a DB client)
  4. Confirm the plugin matches the deployed datastore (mysql/postgres/cassandra/sqlite) and required extensions/versions
  5. Check schema_version_compatibility in config against the actual schema version in the database

Example fix

// before: config.yaml points to database 'temporal' but only 'default' schema was created
// unable to initialize metadata manager: Table 'temporal.namespaces' doesn't exist

// after: create schema and tables first
// temporal-sql-tool --plugin mysql --ep $DB --db temporal setup
// temporal-sql-tool --plugin mysql --ep $DB --db temporal update-schema -d schema/mysql/v57/temporal/versioned
Defensive patterns

Strategy: validation

Validate before calling

// before starting the server, verify DB connectivity and schema:
// db, err := sql.Open("mysql", dsn)
// if err != nil { return err }
// if err := db.Ping(); err != nil { return fmt.Errorf("datastore unreachable: %w", err) }
// var exists int
// db.QueryRow("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='temporal' AND table_name='namespaces'").Scan(&exists)
// if exists == 0 { return errors.New("schema not applied: run temporal-sql-tool setup + update-schema") }

Try / catch

if err := srv.Start(ctx); err != nil {
	if strings.Contains(err.Error(), "unable to initialize metadata manager") {
		log.Fatalf("check persistence config and schema: %v", errors.Unwrap(err))
	}
	log.Fatal(err)
}

Prevention

When it happens

Trigger: temporal.Server.Start(ctx) -> initSystemNamespaces, when the persistence factory cannot construct a MetadataManager: DB connection failure (bad host/port/user/password), missing metadata tables (schema not applied), unsupported or outdated schema version, or bad persistence config for the selected plugin.

Common situations: Fresh deployment where temporal-sql-tool setup was skipped; wrong plugin selected in config (e.g. cassandra vs mysql); network policy/segfault-free firewall blocking the DB port; password rotation in env not reflected in config; running a newer Temporal binary against an older schema that needs update-schema.

Related errors


AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/77ca0bcb1812e886. Report an issue: GitHub.

Appendix: source

Thrown at temporal/server_impl.go:185

		metricsHandler,
		telemetry.NoopTracerProvider,
		serializer,
	)
	factory := persistenceFactoryProvider(persistenceClient.NewFactoryParams{
		DataStoreFactory:           dataStoreFactory,
		Cfg:                        cfg,
		PersistenceMaxQPS:          nil,
		PersistenceNamespaceMaxQPS: nil,
		ClusterName:                persistenceClient.ClusterName(currentClusterName),
		MetricsHandler:             metricsHandler,
		Logger:                     logger,
		Serializer:                 serializer,
	})
	defer factory.Close()

	metadataManager, err := factory.NewMetadataManager()
	if err != nil {
		return fmt.Errorf("unable to initialize metadata manager: %w", err)
	}
	defer metadataManager.Close()
	ctx, cancel := context.WithTimeout(
		headers.SetCallerInfo(ctx, headers.SystemBackgroundHighCallerInfo),
		30*time.Second,
	)
	defer cancel()

	if err = metadataManager.InitializeSystemNamespaces(ctx, currentClusterName); err != nil {
		return fmt.Errorf("unable to register system namespace: %w", err)
	}
	return nil
}

View on GitHub (pinned to bde624efd1)