{"record":{"id":"65797a406bd3620a","repo":"wavetermdev/waveterm","slug":"failed-to-create-backup-directory-w","errorCode":null,"errorMessage":"failed to create backup directory: %w","messagePattern":"failed to create backup directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/filebackup/filebackup.go","lineNumber":57,"sourceCode":"\tdir := filepath.Dir(absFilePath)\n\tbasename := filepath.Base(absFilePath)\n\n\thash := sha256.Sum256([]byte(dir))\n\tdirHash8 := hex.EncodeToString(hash[:])[:8]\n\n\tuuidV7, err := uuid.NewV7()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to generate UUID: %w\", err)\n\t}\n\tuuidStr := uuidV7.String()\n\n\tnow := time.Now()\n\tdateStr := now.Format(\"2006-01-02\")\n\n\tbackupDir := filepath.Join(wavebase.GetWaveCachesDir(), \"waveai-backups\", dateStr)\n\terr = os.MkdirAll(backupDir, 0700)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to create backup directory: %w\", err)\n\t}\n\n\tbackupName := fmt.Sprintf(\"%s.%s.%s.bak\", basename, dirHash8, uuidStr)\n\tbackupPath := filepath.Join(backupDir, backupName)\n\n\terr = os.WriteFile(backupPath, fileData, 0600)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to write backup file: %w\", err)\n\t}\n\n\tmetadata := BackupMetadata{\n\t\tFullPath:  absFilePath,\n\t\tTimestamp: now.Format(time.RFC3339),\n\t\tPerm:      fmt.Sprintf(\"%04o\", fileInfo.Mode().Perm()),\n\t}\n\n\tmetadataJSON, err := json.MarshalIndent(metadata, \"\", \"  \")\n\tif err != nil {","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/filebackup/filebackup.go#L39-L75","documentation":"MakeFileBackup stores AI-file-edit backups under the Wave caches dir (waveai-backups/<YYYY-MM-DD>). Before writing any backup it creates that dated directory with os.MkdirAll(0700). This error wraps the underlying os.MkdirAll failure, meaning the backup directory tree could not be created and no backup was taken (the calling write/edit/delete callback aborts).","triggerScenarios":"Calling MakeFileBackup (via writeTextFileCallback, editTextFileCallback, or deleteTextFileCallback) when os.MkdirAll(GetWaveCachesDir()/waveai-backups/<date>, 0700) fails: caches dir unwritable, path component is a file not a directory, or disk/permission errors.","commonSituations":"WAVE_HOME or cache directory pointing at a read-only or non-existent location; another process created a file named 'waveai-backups' or the date directory; running with a different user than the cache dir owner; full or read-only filesystem.","solutions":["Check permissions and ownership of the Wave caches directory (wavebase.GetWaveCachesDir()) and ensure it is writable by the current user.","Verify no regular file exists at waveai-backups or at the dated subdirectory path that would block MkdirAll; remove or rename it.","Check disk space and mount status (df -h) if the cache volume is full or read-only.","If WAVE_HOME/custom cache config was changed, reset it to a valid writable path and retry the operation."],"exampleFix":"// before: caches dir not writable, MkdirAll fails silently to the user\nos.Chmod(cacheDir, 0500)\n// after: ensure the cache dir is writable before running Wave\nos.Chmod(cacheDir, 0700)","handlingStrategy":"validation","validationCode":"cacheDir := wavebase.GetWaveCachesDir()\nif fi, err := os.Stat(cacheDir); err != nil || !fi.IsDir() {\n    return fmt.Errorf(\"wave caches dir %s unavailable: %w\", cacheDir, err)\n}\nif err := syscall.Access(cacheDir, unix.W_OK); err != nil {\n    return fmt.Errorf(\"wave caches dir %s not writable: %w\", cacheDir, err)\n}","typeGuard":null,"tryCatchPattern":"backupPath, err := filebackup.MakeFileBackup(absPath)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to create backup directory\") {\n        // proceed without backup or surface a clear \"backup storage unavailable\" message\n        log.Warnf(\"backup skipped: %v\", err)\n    }\n    return err\n}","preventionTips":["Ensure WAVE_HOME/cache dir points to a writable local path","Never create files named 'waveai-backups' or a bare date name inside the cache dir","Monitor free space and permissions on the cache volume","Keep one user/owner for the Wave cache directory"],"tags":["filesystem","permissions","backup","go"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}