{"record":{"id":"06d3fab6f011f88e","repo":"gastownhall/beads","slug":"selecting-database-q-w","errorCode":null,"errorMessage":"selecting database %q: %w","messagePattern":"selecting database %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/converged.go","lineNumber":151,"sourceCode":"\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\n// to stop paying GET_LOCK's queue.\n//\n// A NULL answer means the server would not tell us, which is not the same as\n// \"free\": fail closed.\nfunc migrationLockFree(ctx context.Context, db DBConn, lockName string) (bool, error) {\n\tvar free sql.NullInt64\n\tif err := db.QueryRowContext(ctx, \"SELECT IS_FREE_LOCK(?)\", lockName).Scan(&free); err != nil {\n\t\treturn false, fmt.Errorf(\"probing migration lock %q: %w\", lockName, err)","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/converged.go#L133-L169","documentation":"This error is raised when the injected DatabaseSelector callback fails to move the pinned session onto the target database (typically by issuing a quoted USE statement). It wraps the selector's own error with the database name for context. It only fires when the session was not already on the target and the database provably exists.","triggerScenarios":"The selector function (e.g. one issuing USE `dbname`) returns an error — USE fails due to lost connection, insufficient privileges, the database being dropped between the existence probe and the USE, or the context being cancelled.","commonSituations":"Race where another process drops the database between probe and USE; Dolt sql-server grants revoked; server restart mid-open; stale pooled connection dies on first real statement (the USE).","solutions":["Run the operation again — the open path is idempotent and the race window is tiny","Check GRANTs: the connecting user must have usage/access on the target database","Verify the database wasn't concurrently dropped (check server logs or SHOW DATABASES)","Inspect the wrapped %w error for connection-level causes and reconnect"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// confirm the connecting user can select the target database\nrows, _ := db.Query(\"SHOW GRANTS\")\n// verify output includes USAGE/privileges on `dbname`","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"selecting database\") {\n    // check grants / database existence, then retry once\n}","preventionTips":["Grant the bd user privileges on the target database","Avoid dropping databases while clients are opening","Keep the existence-probe-then-USE window short (stock behavior)"],"tags":["go","dolt","database","use-statement"],"backgroundTag":"database-select-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}