{"record":{"id":"a9f22a1e5df50904","repo":"benbjohnson/litestream","slug":"invalid-lock-downgrade-current-s-target-s","errorCode":null,"errorMessage":"invalid lock downgrade: current=%s target=%s","messagePattern":"invalid lock downgrade: current=(.+?) target=(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"vfs.go","lineNumber":2282,"sourceCode":"\tfor pgno := range f.dirty {\n\t\tif v := int64(pgno) * int64(pageSize); v > size {\n\t\t\tsize = v\n\t\t}\n\t}\n\tf.mu.Unlock()\n\n\tf.logger.Debug(\"file size\", \"size\", size)\n\treturn size, nil\n}\n\nfunc (f *VFSFile) Lock(elock sqlite3vfs.LockType) error {\n\tf.logger.Debug(\"locking file\", \"lock\", elock)\n\n\tf.mu.Lock()\n\tdefer f.mu.Unlock()\n\n\tif elock < f.lockType {\n\t\treturn fmt.Errorf(\"invalid lock downgrade: current=%s target=%s\", f.lockType, elock)\n\t}\n\n\tif elock >= sqlite3vfs.LockReserved {\n\t\t// Wait for any disable operation to complete before allowing RESERVED lock.\n\t\t// This prevents new write transactions from starting during disable.\n\t\tfor f.disabling {\n\t\t\tf.logger.Debug(\"waiting for disable to complete before acquiring RESERVED lock\")\n\t\t\tf.cond.Wait()\n\t\t}\n\n\t\t// Reject write-intent locks when writes are disabled. Since we always\n\t\t// report OpenReadWrite to SQLite (to support cold enable), SQLite may\n\t\t// attempt write transactions even when writes are logically disabled.\n\t\tif !f.writeEnabled {\n\t\t\treturn sqlite3vfs.ReadOnlyError\n\t\t}\n\t}\n","sourceCodeStart":2264,"sourceCodeEnd":2300,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/vfs.go#L2264-L2300","documentation":"VFSFile.Lock rejected an attempt to move to a weaker lock level than currently held (e.g. EXCLUSIVE down to RESERVED). SQLite's locking protocol only escalates; a downgrade request indicates a protocol violation inside the VFS or misuse of the file handle.","triggerScenarios":"Thrown at vfs.go:2282 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Report as a bug — SQLite itself should never issue downgrades through this path","Check for concurrent misuse of the same VFS file handle"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}