micro/go-micro · error

model/postgres: create index: %w

Error message

model/postgres: create index: %w

What it means

During Register, after creating the table, the postgres model creates a non-unique index for every schema field flagged Index (excluding keys) via CREATE INDEX IF NOT EXISTS. If Postgres rejects the index creation, the error is wrapped as "model/postgres: create index" with the driver error as the cause.

Source

Thrown at model/postgres/postgres.go:74

		if f.IsKey {
			col += " PRIMARY KEY"
		}
		cols = append(cols, col)
	}

	query := fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (%s)", quoteIdent(schema.Table), strings.Join(cols, ", "))
	if _, err := d.db.Exec(query); err != nil {
		return fmt.Errorf("model/postgres: create table: %w", err)
	}

	for _, f := range schema.Fields {
		if f.Index && !f.IsKey {
			idx := fmt.Sprintf("CREATE INDEX IF NOT EXISTS %s ON %s (%s)",
				quoteIdent("idx_"+schema.Table+"_"+f.Column),
				quoteIdent(schema.Table),
				quoteIdent(f.Column))
			if _, err := d.db.Exec(idx); err != nil {
				return fmt.Errorf("model/postgres: create index: %w", err)
			}
		}
	}

	return nil
}

func (d *postgresModel) schema(v interface{}) (*model.Schema, error) {
	t := model.ResolveType(v)
	d.mu.RLock()
	s, ok := d.types[t]
	d.mu.RUnlock()
	if !ok {
		return nil, model.ErrNotRegistered
	}
	return s, nil
}

View on GitHub (pinned to 24529f1404)

Solutions

  1. Inspect the wrapped driver error to see which index/column failed.
  2. Shorten the table or column name so idx_<table>_<column> fits within 63 characters.
  3. Grant CREATE privilege on the schema/table to the connecting role.
  4. Drop or rename the conflicting existing index, or manage indexes via migrations instead.

Example fix

// before
Field{Name: "very_long_column_name_that_pushes_identifier_over_limit", Index: true}

// after
// rename column or disable auto index and create it manually
Field{Name: "long_col", Index: true}
-- manual: CREATE INDEX IF NOT EXISTS idx_tbl_long_col ON tbl (long_col);
Defensive patterns

Strategy: try-catch

Validate before calling

// check identifier length limit (Postgres max 63 bytes) before Register
func indexNameFits(table, column string) bool {
    return len("idx_"+table+"_"+column) <= 63
}

Try / catch

if err := store.Register(ctx, &User{}); err != nil {
    if strings.Contains(err.Error(), "create index") {
        log.Printf("index creation failed (check name length/privileges): %v", err)
        // optionally continue without secondary indexes
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: Registering a schema where an indexed field's column name is invalid/reserved, the table owner lacks CREATE index privilege, the index name exceeds PostgreSQL's 63-character identifier limit, or a conflicting index of a different definition exists under the same name.

Common situations: Long table+column names producing idx_ names > 63 chars (Postgres silently truncates or errors in some toolchains), restricted production DB roles, or schema changes where an existing index conflicts.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/efe4a56e6341451c. Report an issue: GitHub.