{"record":{"id":"000e378c7b61d137","repo":"wavetermdev/waveterm","slug":"filemutex-new-error-w","errorCode":null,"errorMessage":"filemutex new error: %w","messagePattern":"filemutex new error: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pkg/wavebase/wavebase-win.go","lineNumber":22,"sourceCode":"//go:build windows\n\npackage wavebase\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"path/filepath\"\n\n\t\"github.com/alexflint/go-filemutex\"\n)\n\nfunc AcquireWaveLock() (FDLock, error) {\n\tdataHomeDir := GetWaveDataDir()\n\tlockFileName := filepath.Join(dataHomeDir, WaveLockFile)\n\tlog.Printf(\"[base] acquiring lock on %s\\n\", lockFileName)\n\tm, err := filemutex.New(lockFileName)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"filemutex new error: %w\", err)\n\t}\n\terr = m.TryLock()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"filemutex trylock error: %w\", err)\n\t}\n\treturn m, nil\n}\n","sourceCodeStart":4,"sourceCodeEnd":30,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wavebase/wavebase-win.go#L4-L30","documentation":"The Windows implementation of AcquireWaveLock creates a filemutex on <WaveDataDir>/<WaveLockFile> to ensure only one Wave instance runs. filemutex.New fails when the lock file path cannot be set up (invalid path, directory missing, or OS-level CreateFile failure), wrapped as 'filemutex new error: %w'.","triggerScenarios":"Calling AcquireWaveLock at startup when GetWaveDataDir() returns a path that does not exist or is not writable, the path contains illegal characters, or filemutex cannot create/open the lock file on Windows (ERROR_PATH_NOT_FOUND, access denied).","commonSituations":"WAVE_DATA_DIR env var overridden to a nonexistent or invalid directory; data dir deleted by cleanup tools while the app runs; path with characters Windows rejects; running from a context without permission to the data directory (service account, restricted user).","solutions":["Read the wrapped %w error for the exact Windows error code","Ensure the data directory exists: create GetWaveDataDir()'s path (os.MkdirAll) before acquiring the lock","Check/fix the WAVE_DATA_DIR override to a valid, writable path","Run the app as a user with write access to the data directory"],"exampleFix":"// before\nlock, err := wavebase.AcquireWaveLock() // data dir missing\n// after\nif err := os.MkdirAll(wavebase.GetWaveDataDir(), 0755); err != nil {\n    return err\n}\nlock, err := wavebase.AcquireWaveLock()","handlingStrategy":"try-catch","validationCode":"dataDir := wavebase.GetWaveDataDir()\nif err := os.MkdirAll(dataDir, 0755); err != nil {\n    return fmt.Errorf(\"cannot prepare data dir %s: %w\", dataDir, err)\n}\nif err := unix.Access(dataDir, unix.W_OK); err != nil {\n    return fmt.Errorf(\"data dir not writable: %w\", err)\n}","typeGuard":"func dataDirReady() bool {\n    dir := wavebase.GetWaveDataDir()\n    info, err := os.Stat(dir)\n    return err == nil && info.IsDir()\n}","tryCatchPattern":"lock, err := wavebase.AcquireWaveLock()\nif err != nil {\n    if strings.Contains(err.Error(), \"filemutex new error\") {\n        // repair path: ensure data dir exists, then retry once\n        os.MkdirAll(wavebase.GetWaveDataDir(), 0755)\n        lock, err = wavebase.AcquireWaveLock()\n    }\n    if err != nil { return err }\n}","preventionTips":["Do not set WAVE_DATA_DIR to nonexistent or invalid paths","Ensure the data directory exists at install time and is not removed by cleaners","Run the app under a user account with write access to the data directory","On Windows, check antivirus interference with lock-file creation"],"tags":["go","windows","file-locking","startup"],"backgroundTag":"file-lock-acquisition-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}