benbjohnson/litestream · error

invalid unlock target: %s

Error message

invalid unlock target: %s

What it means

VFSFile.Unlock rejected an unlock target other than SHARED or NONE — SQLite only ever unlocks down to those levels. Any other target means corrupted lock-state tracking or a misbehaving SQLite build issuing invalid unlock transitions.

Source

Thrown at vfs.go:2331

			}
			f.vfs.writeMu.Unlock()
		}
		f.inTransaction = true
		f.logger.Debug("transaction started", "expectedTXID", f.expectedTXID)
	}

	f.lockType = elock
	return nil
}

func (f *VFSFile) Unlock(elock sqlite3vfs.LockType) error {
	f.logger.Debug("unlocking file", "lock", elock)

	f.mu.Lock()
	defer f.mu.Unlock()

	if elock != sqlite3vfs.LockShared && elock != sqlite3vfs.LockNone {
		return fmt.Errorf("invalid unlock target: %s", elock)
	}

	if f.writeEnabled && f.inTransaction && elock < sqlite3vfs.LockReserved {
		f.inTransaction = false
		if f.vfs != nil {
			f.vfs.writeMu.Lock()
			if f.vfs.writeFile == f {
				f.vfs.writeFile = nil
			}
			f.vfs.writeMu.Unlock()
		}
		f.logger.Debug("transaction ended", "dirtyPages", len(f.dirty))
		f.cond.Broadcast() // Wake up SetWriteEnabledWithTimeout if waiting
	}

	f.lockType = elock

	// Copy pending index to main index and invalidate affected pages in cache.

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Report as a bug with the SQLite version in use
  2. Check for a non-standard SQLite build driving the VFS
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at vfs.go:2331 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06). Data as JSON: /api/errors/bfbfb95f196145d4. Report an issue: GitHub.