{"record":{"id":"232d6218f473a87e","repo":"gastownhall/beads","slug":"probing-database-q-existence-w","errorCode":null,"errorMessage":"probing database %q existence: %w","messagePattern":"probing database %q existence: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/converged.go","lineNumber":143,"sourceCode":"// its life (be-bv7x). Probe with a query that always succeeds, then act.\nfunc selectTargetDatabase(ctx context.Context, db DBConn, databaseName string, selector DatabaseSelector) (bool, string, error) {\n\tvar current sql.NullString\n\tif err := db.QueryRowContext(ctx, \"SELECT DATABASE()\").Scan(&current); err != nil {\n\t\treturn false, \"\", fmt.Errorf(\"reading current database: %w\", err)\n\t}\n\tif current.Valid && current.String == databaseName {\n\t\treturn true, \"\", nil\n\t}\n\tif selector == nil {\n\t\treturn false, \"\", nil\n\t}\n\n\tvar exists int\n\tif err := db.QueryRowContext(ctx,\n\t\t\"SELECT COUNT(*) FROM information_schema.schemata WHERE schema_name = ?\",\n\t\tdatabaseName,\n\t).Scan(&exists); err != nil {\n\t\treturn false, \"\", fmt.Errorf(\"probing database %q existence: %w\", databaseName, err)\n\t}\n\tif exists == 0 {\n\t\treturn false, \"\", nil\n\t}\n\n\tquoted, err := selector(ctx, db, databaseName)\n\tif err != nil {\n\t\treturn false, \"\", fmt.Errorf(\"selecting database %q: %w\", databaseName, err)\n\t}\n\tif quoted == \"\" {\n\t\treturn false, \"\", fmt.Errorf(\"selecting database %q: selector returned no quoted name\", databaseName)\n\t}\n\treturn true, quoted, nil\n}\n\n// migrationLockFree reports whether the database-scoped migration lock is\n// currently unheld. IS_FREE_LOCK is a read: it never queues, never acquires,\n// and costs one round trip, which is the entire point — the fast path exists","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/converged.go#L125-L161","documentation":"This error wraps a failure from the information_schema.schemata probe that selectTargetDatabase uses to check whether the target Dolt database exists before issuing a USE. The probe is deliberately an always-succeeds query: on Dolt, a failing statement (like a USE of a missing database) pins the pooled session to a stale catalog snapshot, poisoning the connection. The %w carries the underlying driver error from the schemata COUNT query.","triggerScenarios":"The SELECT COUNT(*) FROM information_schema.schemata WHERE schema_name = ? query itself fails — the SQL connection is broken/dropped mid-probe, the server rejects the query, the context is cancelled, or the driver returns an unexpected error. Not triggered when the database simply doesn't exist (that returns exists==0, no error).","commonSituations":"Dolt sql-server restarted or network blipped between pooled calls; connection idle-timed out by the server; context deadline exceeded during a slow open; permissions preventing read of information_schema on a restricted server.","solutions":["Check connection health: ping the server and verify the Dolt sql-server is up before retrying bd","Inspect the wrapped (%w) driver error for the root cause (EOF, connection refused, context deadline)","Retry the operation — the probe is read-only and safe to re-run","If context timeouts recur, increase the timeout on bd's database connection settings"],"exampleFix":"// before: blind retry loop on any failure\nif err := probe(ctx); err != nil { return err }\n// after: detect dead connection and reconnect/retry\nif err := probe(ctx); err != nil {\n    if dberrors.IsConnErr(err) { db = reopen(ctx); continue }\n    return err\n}","handlingStrategy":"retry","validationCode":"// before relying on the probe, confirm the server is reachable\nif err := db.PingContext(ctx); err != nil {\n    return fmt.Errorf(\"dolt server unreachable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if _, err := alreadyConverged(ctx, db, name, sel); err != nil {\n    var connErr *net.OpError\n    if errors.As(err, &connErr) || errors.Is(err, context.DeadlineExceeded) {\n        // transient: retry with backoff\n    }\n    return err\n}","preventionTips":["Keep the Dolt sql-server monitored/restarted under supervision","Set generous but bounded context timeouts for open-path probes","Treat alreadyConverged errors as advisory — the locked path is the safe fallback"],"tags":["go","dolt","database","information-schema"],"backgroundTag":"database-existence-probe-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}