wavetermdev/waveterm · error
failed to write file: %w
Error message
failed to write file: %w
What it means
WriteAppFile in pkg/waveappstore writes a file into the app's directory under ~/waveapps/<ns>/<app>. This error wraps the underlying os.WriteFile failure after the parent directory was already created successfully (waveappstore.go:282-284). It means the path resolved fine but the actual write syscall failed, and the wrapped OS error (permission denied, disk full, is-a-directory, etc.) is in the %w chain.
Source
Thrown at pkg/waveappstore/waveappstore.go:283
return fmt.Errorf("invalid appId: %w", err)
}
appDir, err := GetAppDir(appId)
if err != nil {
return err
}
filePath, err := validateAndResolveFilePath(appDir, fileName)
if err != nil {
return err
}
if err := os.MkdirAll(filepath.Dir(filePath), 0755); err != nil {
return fmt.Errorf("failed to create directory: %w", err)
}
if err := os.WriteFile(filePath, contents, 0644); err != nil {
return fmt.Errorf("failed to write file: %w", err)
}
return nil
}
func ReadAppFile(appId string, fileName string) (*FileData, error) {
if err := ValidateAppId(appId); err != nil {
return nil, fmt.Errorf("invalid appId: %w", err)
}
appDir, err := GetAppDir(appId)
if err != nil {
return nil, err
}
filePath, err := validateAndResolveFilePath(appDir, fileName)
if err != nil {
return nil, errView on GitHub (pinned to a4447c1563)
Solutions
- Inspect the wrapped error with errors.Unwrap or %v on the returned error to get the exact errno (EACCES, ENOSPC, EISDIR).
- If permission denied: check ownership/permissions of ~/waveapps/<ns>/<app>/ and chown/chmod back to the current user.
- If the target path is a directory, remove or rename the conflicting directory.
- If disk full, free space on the home filesystem and retry.
- Ensure fileName is a relative path inside the app dir and the appId is valid so the resolved path is the intended one.
Example fix
// before: blindly retrying a failed write
err := waveappstore.WriteAppFile(appId, "app.go", contents)
if err != nil { return err } // opaque
// after: surface and handle the wrapped OS error
if err := waveappstore.WriteAppFile(appId, "app.go", contents); err != nil {
if errors.Is(err, fs.ErrPermission) {
return fmt.Errorf("cannot write %s: fix ownership of ~/waveapps", appId)
}
if errors.Is(err, fs.ErrExist) {
return fmt.Errorf("a directory exists at the target path")
}
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
// Go: pre-check writability of the target before calling WriteAppFile
func canWrite(appId, fileName string) error {
dir, err := waveappstore.GetAppDir(appId)
if err != nil { return err }
target := filepath.Join(dir, filepath.Clean(fileName))
if fi, err := os.Stat(target); err == nil && fi.IsDir() {
return fmt.Errorf("target is a directory: %s", target)
}
f, err := os.OpenFile(filepath.Dir(target), os.O_WRONLY, 0)
if err != nil { return err }
f.Close()
return nil
} Try / catch
err := waveappstore.WriteAppFile(appId, fileName, contents)
if err != nil {
switch {
case errors.Is(err, fs.ErrPermission):
// fix ownership/permissions, prompt user
case errors.Is(err, fs.ErrExist):
// directory conflict at target path
default:
// surface wrapped errno
}
} Prevention
- Never create directories whose names collide with file names you will write.
- Run Wave as a normal user so ~/waveapps stays user-owned.
- Check disk space before bulk writes.
- Use errors.Is with fs error sentinels to branch on the real errno.
When it happens
Trigger: Calling WriteAppFile (or the WriteAppFileCommand / WriteAppGoFileCommand RPCs) where os.WriteFile fails: target path exists as a directory, the file or parent dir is not writable, the filesystem is read-only or full, or an immutable/locked file is being overwritten.
Common situations: A directory named like the target file exists (e.g. someone created 'app.go/' by accident); ~/waveapps owned by another user after running the terminal with sudo; disk quota exceeded; editing an app while a sync/backup tool holds the file locked on Windows.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- failed to create backup directory: %w
- failed to create socket directory: %w
- failed to create log directory: %w
- failed to open log file: %w
- failed to read directory: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/104703cfc3bc8a66.
Report an issue: GitHub.