multica-ai/multica · error
inspect concurrent index %q: %w
Error message
inspect concurrent index %q: %w
What it means
The migrate tool's catalog probe failed: it queries pg_class/pg_namespace/pg_index via to_regclass($1) to decide whether a concurrently-built index exists and is valid before retrying a failed CREATE INDEX CONCURRENTLY migration. A query error here means the catalog read itself failed — connection loss, cancellation, or permissions on system catalogs.
Source
Thrown at server/cmd/migrate/main.go:177
// Without this guard, CREATE INDEX ... IF NOT EXISTS would treat the leftover
// relation as success and allow a later migration to drop the still-valid old
// index. Non-index relations fail closed instead of being dropped implicitly.
func cleanupInvalidConcurrentIndexHook(indexRegclass string) preMigrationHook {
return func(ctx context.Context, pool *pgxpool.Pool) error {
var schemaName, relationName string
var isIndex, isValid bool
err := pool.QueryRow(ctx, `
SELECT n.nspname, c.relname, c.relkind = 'i', COALESCE(i.indisvalid, FALSE)
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_index i ON i.indexrelid = c.oid
WHERE c.oid = to_regclass($1)
`, indexRegclass).Scan(&schemaName, &relationName, &isIndex, &isValid)
if errors.Is(err, pgx.ErrNoRows) {
return nil
}
if err != nil {
return fmt.Errorf("inspect concurrent index %q: %w", indexRegclass, err)
}
if !isIndex {
return fmt.Errorf("relation %q exists but is not an index", indexRegclass)
}
if isValid {
return nil
}
qualifiedName := pgx.Identifier{schemaName, relationName}.Sanitize()
if _, err := pool.Exec(ctx, "DROP INDEX CONCURRENTLY IF EXISTS "+qualifiedName); err != nil {
return fmt.Errorf("drop invalid concurrent index %s: %w", qualifiedName, err)
}
slog.Warn("removed invalid index before migration retry", "index", qualifiedName)
return nil
}
}
func runTaskUsageHourlyHook(ctx context.Context, pool *pgxpool.Pool) error {View on GitHub (pinned to 2c0912b6ec)
Solutions
- Re-run `migrate up` — the advisory lock and per-version EXISTS checks make it resumable
- Check the wrapped error: if auth-related, grant the migration role read on system catalogs or use a privileged role
- Verify the index name passed in the hook is a valid qualified identifier (schema.index)
Defensive patterns
Strategy: retry
Try / catch
if err != nil {
return fmt.Errorf("inspect concurrent index %q: %w", indexRegclass, err)
} Prevention
- Keep the migrate role's access to system catalogs intact
- Re-run migrations after transient connection errors — everything is resumable
When it happens
Trigger: Connection dropped while inspecting; ctx cancelled; indexRegclass malformed enough to break parameter binding; running as a role denied SELECT on pg_class.
Common situations: Rare in practice; most often a transient network blip or an operator-killed migration run at exactly this step.
Related errors
- relation %q exists but is not an index
- drop invalid concurrent index %s: %w
- task_usage_hourly pre-103 hook: %w
- attribution strict-constraint pre-198 hook: %w
- invalid schema migrations table %q: %w
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/92f8ee08e4dd6f51.
Report an issue: GitHub.