{"record":{"id":"88fe9579d3140449","repo":"gastownhall/beads","slug":"probing-migration-lock-q-w","errorCode":null,"errorMessage":"probing migration lock %q: %w","messagePattern":"probing migration lock %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/converged.go","lineNumber":169,"sourceCode":"\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)\n\t}\n\tif !free.Valid {\n\t\treturn false, nil\n\t}\n\treturn free.Int64 == 1, nil\n}\n\n// doltIgnoreSeeded reports whether every canonical dolt_ignore pattern\n// seedDoltIgnorePatterns would assert is already present. It is the read-only\n// counterpart of that seed and shares its version gate: a pattern whose flip\n// migration has not been reached yet is not expected, exactly as the seed\n// would not insert it. mainVersionAtLeast is a lower bound on the main cursor\n// that the caller has already established, so this read costs one round trip\n// rather than three.\n//\n// Presence is judged on the pattern alone, never on its ignored value, because\n// INSERT IGNORE would leave an explicit operator override (a pattern recorded\n// with ignored=false) untouched. Reporting such a row as missing would send","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/converged.go#L151-L187","documentation":"migrationLockFree probes the database-scoped migration lock with SELECT IS_FREE_LOCK(?) — a read that never queues or acquires. This error wraps a failure of that IS_FREE_LOCK query itself. A NULL result is handled separately (fail closed to the locked path, no error); only an actual query error produces this message.","triggerScenarios":"The SELECT IS_FREE_LOCK(?) query fails: broken pooled connection, context cancelled/deadline exceeded, server rejected the statement, or the driver errored mid-scan.","commonSituations":"Dolt sql-server connection dropped between earlier probes and this one; context timeout during a slow open on a loaded shared rig; a Dolt build/server version that rejects or errors on IS_FREE_LOCK.","solutions":["Retry — the probe is read-only and alreadyConverged fails closed (falls back to the normal locked path), so the error may be transient","Inspect the wrapped %w driver error; if connection-level, reconnect and re-run bd","If IS_FREE_LOCK is unsupported by your Dolt server version, upgrade the server or skip the lock-free fast path","Check context timeouts if deadlines recur on a busy shared server"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// verify the server supports named locks before fast-path probing\nvar v string\n_ = db.QueryRow(\"SELECT VERSION()\").Scan(&v) // check Dolt version supports IS_FREE_LOCK","typeGuard":null,"tryCatchPattern":"if _, err := alreadyConverged(...); err != nil {\n    // alreadyConverged errors are advisory: proceed down the locked MigrateUp path\n    return MigrateUp(ctx, db)\n}","preventionTips":["Treat alreadyConverged failures as 'not converged', never fatal","Ensure the Dolt server version supports IS_FREE_LOCK","Retry transient connection errors rather than surfacing them to users"],"tags":["go","dolt","locking","is-free-lock"],"backgroundTag":"migration-lock-probe-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}