wavetermdev/waveterm · error
filemutex trylock error: %w
Error message
filemutex trylock error: %w
What it means
AcquireWaveLock in pkg/wavebase wraps a failure from filemutex.New's TryLock() — the process could not obtain an exclusive OS-level file lock on the Wave lock file. TryLock returns a non-nil error when the lock file is already held by another process (or an OS-level locking failure occurs). It is thrown at startup so the app never runs two instances against the same data directory.
Source
Thrown at pkg/wavebase/wavebase-win.go:26
import (
"fmt"
"log"
"path/filepath"
"github.com/alexflint/go-filemutex"
)
func AcquireWaveLock() (FDLock, error) {
dataHomeDir := GetWaveDataDir()
lockFileName := filepath.Join(dataHomeDir, WaveLockFile)
log.Printf("[base] acquiring lock on %s\n", lockFileName)
m, err := filemutex.New(lockFileName)
if err != nil {
return nil, fmt.Errorf("filemutex new error: %w", err)
}
err = m.TryLock()
if err != nil {
return nil, fmt.Errorf("filemutex trylock error: %w", err)
}
return m, nil
}
View on GitHub (pinned to a4447c1563)
Solutions
- Check for and close any already-running Wave process, then retry launch
- Inspect the wrapped error: if it indicates the lock is simply held, that is the single-instance guard working — reuse the running instance
- Verify the lock file directory is writable and on a filesystem supporting file locks (not NFS/SMB)
- If a dead process left the file, delete the stale lock file (the lock itself is released by the OS when the process dies)
Example fix
// before: app exits with 'filemutex trylock error: resource temporarily unavailable'
// after: detect double-launch before calling
if !canAcquireLock(lockFileName) {
fmt.Println("Wave is already running; exiting")
os.Exit(0)
}
lock, err := wavebase.AcquireWaveLock(lockFileName) Defensive patterns
Strategy: try-catch
Validate before calling
// before launching
if _, err := os.Stat(lockFilePath); err == nil {
if procRunning('waveterm') { fmt.Println("already running"); os.Exit(0) }
} Try / catch
lock, err := wavebase.AcquireWaveLock(name)
if err != nil {
if strings.Contains(err.Error(), "trylock") {
log.Fatalf("another instance holds the lock: %v", err)
}
return err
} Prevention
- Ensure single-instance launching (detect existing process before acquire)
- Place lock files on local filesystems that support flock/LockFileEx, never NFS/SMB
- Verify directory write permissions before startup
When it happens
Trigger: Calling AcquireWaveLock (typically from main) when another Wave process already holds TryLock on lockFileName; or the underlying syscall (flock/LockFileEx) fails due to filesystem/permissions issues.
Common situations: Launching Wave while an existing instance is still running; a stale/crashed process holding the lock; running from a network or read-only filesystem where locking is unsupported; permission problems on the lock file.
Related errors
- filemutex new error: %w
- setting auth key: %v
- error getting client: %v
- process group id not supported on windows
- sending signals is not supported on Windows
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/36a0c74fb076c1c9.
Report an issue: GitHub.