micro/go-micro · error
cannot create metadata index
Error message
cannot create metadata index
What it means
After successfully creating the table, initTable executes a CREATE INDEX statement for the metadata column and wraps failures with 'cannot create metadata index'. It means the GIN/btree index on the metadata JSONB column could not be created, even though the table itself exists.
Source
Thrown at store/postgres/pgx/pgx.go:101
if err != nil {
return nil, Queries{}, err
}
}
return dbObj.conn, dbObj.tables[table], nil
}
func (s *sqlStore) initTable(database, table string) error {
db := s.databases[database].conn
_, err := db.Exec(s.options.Context, fmt.Sprintf(createTable, database, table))
if err != nil {
return errors.Wrap(err, "cannot create table")
}
_, err = db.Exec(s.options.Context, fmt.Sprintf(createMDIndex, table, database, table))
if err != nil {
return errors.Wrap(err, "cannot create metadata index")
}
_, err = db.Exec(s.options.Context, fmt.Sprintf(createExpiryIndex, table, database, table))
if err != nil {
return errors.Wrap(err, "cannot create expiry index")
}
s.databases[database].tables[table] = NewQueries(database, table)
return nil
}
func (s *sqlStore) initDB(database string) error {
if len(s.options.Nodes) == 0 {
s.options.Nodes = []string{"postgresql://root@localhost:26257?sslmode=disable"}
}
source := s.options.Nodes[0]View on GitHub (pinned to 24529f1404)
Solutions
- Grant INDEX/CREATE privilege: GRANT CREATE ON SCHEMA public TO <user> (or table owner must run the index DDL).
- Check the wrapped PostgreSQL error for the specific reason.
- Retry initialization if a concurrent instance held locks during index creation.
- Create the index manually with the exact definition the store expects.
- Confirm required extensions (e.g. for JSONB GIN indexes) are available.
Example fix
// before // db.Exec(createMDIndex...) fails with permission denied // after GRANT CREATE ON SCHEMA public TO micro_user; // or pre-create index manually before app start
Defensive patterns
Strategy: validation
Validate before calling
// before init var canIdx bool conn.QueryRow(ctx, "SELECT has_schema_privilege(current_user, 'public', 'CREATE')").Scan(&canIdx) // verify extension support for the index method, e.g.: // SELECT EXISTS (SELECT 1 FROM pg_extension WHERE extname='...');
Try / catch
if err := store.Init(); err != nil {
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) && pgErr.Code == "42P17" || pgErr.Code == "42501" {
// pre-create index manually or fix privileges, then retry
}
return err
} Prevention
- Ensure the app DB role can create indexes (schema CREATE privilege or table ownership).
- Serialize initialization (single instance or advisory lock) to avoid lock contention.
- Pre-create indexes in migration scripts for restricted environments.
- Check required extensions are installed in the target database.
- Inspect wrapped PgError codes for precise diagnosis.
When it happens
Trigger: First access to an uninitialized table where the CREATE INDEX for metadata fails: missing table (created concurrently?), insufficient privileges to create indexes, shared lock contention, or DB not supporting the index type.
Common situations: DB user can CREATE TABLE but not INDEX; concurrent store instances racing on initialization causing transient lock timeouts; managed Postgres restricting certain index types (e.g. no GIN extension).
Related errors
- cannot create table
- cannot create expiry index
- unsupported statement
- model/postgres: create index: %w
- model/postgres: create: %w
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/4e1b32c3a9e24fa3.
Report an issue: GitHub.