larksuite/cli · error
cannot write file: %w
Error message
cannot write file: %w
What it means
SaveResponse wraps failures from the FileIO WriteFile call as 'cannot write file: %w' when the error is a typed fileio.WriteError. This means the directory was created (or existed) but writing the response body to outputPath failed. It is the file-write counterpart to 'create directory' and 'unsafe output path'.
Source
Thrown at internal/client/response.go:222
// ── File saving ──
// SaveResponse writes an API response body to the given outputPath and returns metadata.
// It delegates to FileIO.Save for path validation and atomic write; fio must not be nil.
func SaveResponse(fio fileio.FileIO, resp *larkcore.ApiResp, outputPath string) (map[string]interface{}, error) {
result, err := fio.Save(outputPath, fileio.SaveOptions{
ContentType: resp.Header.Get("Content-Type"),
ContentLength: int64(len(resp.RawBody)),
}, bytes.NewReader(resp.RawBody))
if err != nil {
var me *fileio.MkdirError
var we *fileio.WriteError
switch {
case errors.Is(err, fileio.ErrPathValidation):
return nil, fmt.Errorf("unsafe output path: %w", err)
case errors.As(err, &me):
return nil, fmt.Errorf("create directory: %w", err)
case errors.As(err, &we):
return nil, fmt.Errorf("cannot write file: %w", err)
default:
return nil, fmt.Errorf("cannot write file: %w", err)
}
}
resolvedPath, err := fio.ResolvePath(outputPath)
if err != nil || resolvedPath == "" {
resolvedPath = outputPath
}
return map[string]interface{}{
"saved_path": resolvedPath,
"size_bytes": result.Size(),
"content_type": resp.Header.Get("Content-Type"),
}, nil
}
// ResolveFilename picks a filename from the response headers.
// Priority: Content-Disposition filename > Content-Type extension > "download.bin".View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Check free disk space and write permissions for the target file's directory
- Verify outputPath is not an existing directory
- Write to a writable location (temp dir or FileIO-allowed tree via runtime.ResolveSavePath)
- Read the wrapped cause for the exact OS error and fix accordingly
Example fix
// before client.SaveResponse(resp, "/mnt/readonly/response.json") // after client.SaveResponse(resp, filepath.Join(os.TempDir(), "response.json"))
Defensive patterns
Strategy: try-catch
Validate before calling
if st, err := os.Stat(outputPath); err == nil && st.IsDir() {
return fmt.Errorf("%s is a directory", outputPath)
} Type guard
var we *fileio.WriteError
if errors.As(err, &we) { /* handle write failure specifically */ } Try / catch
_, err := client.SaveResponse(resp, outputPath)
if err != nil {
var we *fileio.WriteError
if errors.As(err, &we) {
// inspect we's cause: disk full / permission / is-a-directory
}
return err
} Prevention
- Ensure the target directory is writable and has free disk space
- Confirm outputPath is a file path, not an existing directory
- Avoid saving to read-only mounts or synced/locked locations
- Use runtime.ResolveSavePath to land on a valid writable path
When it happens
Trigger: Calling SaveResponse with an outputPath where WriteFile fails: disk full, permission denied on the target file, target path is a directory, or the storage backend rejects the write after mkdir succeeded.
Common situations: Read-only target directories, quota/disk-full conditions, antivirus or sync tools locking the file, saving onto a mounted volume that went read-only, or a FileIO backend write limit.
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
- invalid chart size: {size!r}
- create directory: %w
- open lock file: %w
- create temp file: %w
- No visible worksheet matched
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/fffcaacec25e1e99.
Report an issue: GitHub.