{"record":{"id":"92f8ee08e4dd6f51","repo":"multica-ai/multica","slug":"inspect-concurrent-index-q-w","errorCode":null,"errorMessage":"inspect concurrent index %q: %w","messagePattern":"inspect concurrent index %q: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/migrate/main.go","lineNumber":177,"sourceCode":"// Without this guard, CREATE INDEX ... IF NOT EXISTS would treat the leftover\n// relation as success and allow a later migration to drop the still-valid old\n// index. Non-index relations fail closed instead of being dropped implicitly.\nfunc cleanupInvalidConcurrentIndexHook(indexRegclass string) preMigrationHook {\n\treturn func(ctx context.Context, pool *pgxpool.Pool) error {\n\t\tvar schemaName, relationName string\n\t\tvar isIndex, isValid bool\n\t\terr := pool.QueryRow(ctx, `\n\t\t\tSELECT n.nspname, c.relname, c.relkind = 'i', COALESCE(i.indisvalid, FALSE)\n\t\t\tFROM pg_class c\n\t\t\tJOIN pg_namespace n ON n.oid = c.relnamespace\n\t\t\tLEFT JOIN pg_index i ON i.indexrelid = c.oid\n\t\t\tWHERE c.oid = to_regclass($1)\n\t\t`, indexRegclass).Scan(&schemaName, &relationName, &isIndex, &isValid)\n\t\tif errors.Is(err, pgx.ErrNoRows) {\n\t\t\treturn nil\n\t\t}\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"inspect concurrent index %q: %w\", indexRegclass, err)\n\t\t}\n\t\tif !isIndex {\n\t\t\treturn fmt.Errorf(\"relation %q exists but is not an index\", indexRegclass)\n\t\t}\n\t\tif isValid {\n\t\t\treturn nil\n\t\t}\n\n\t\tqualifiedName := pgx.Identifier{schemaName, relationName}.Sanitize()\n\t\tif _, err := pool.Exec(ctx, \"DROP INDEX CONCURRENTLY IF EXISTS \"+qualifiedName); err != nil {\n\t\t\treturn fmt.Errorf(\"drop invalid concurrent index %s: %w\", qualifiedName, err)\n\t\t}\n\t\tslog.Warn(\"removed invalid index before migration retry\", \"index\", qualifiedName)\n\t\treturn nil\n\t}\n}\n\nfunc runTaskUsageHourlyHook(ctx context.Context, pool *pgxpool.Pool) error {","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/migrate/main.go#L159-L195","documentation":"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.","triggerScenarios":"Connection dropped while inspecting; ctx cancelled; indexRegclass malformed enough to break parameter binding; running as a role denied SELECT on pg_class.","commonSituations":"Rare in practice; most often a transient network blip or an operator-killed migration run at exactly this step.","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)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil {\n    return fmt.Errorf(\"inspect concurrent index %q: %w\", indexRegclass, err)\n}","preventionTips":["Keep the migrate role's access to system catalogs intact","Re-run migrations after transient connection errors — everything is resumable"],"tags":["go","postgres","migration","catalog","index"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}