ipfs/kubo · error
writing %s: %w
Error message
writing %s: %w
What it means
After a successful Sync, the temp file is closed and, inside atomicfile, renamed over the target. This error wraps a failure from file.Close(), which for atomicfile includes the rename operation. The export therefore did not complete: either the flush/close syscall failed or the rename could not replace the target (e.g. it cannot be renamed over).
Source
Thrown at core/commands/keystore.go:379
outPath, err = resolveSymlink(outPath)
if err != nil {
return err
}
file, err := atomicfile.New(outPath, exportedKeyFileMode)
if err != nil {
return fmt.Errorf("creating temporary file for %s: %w", outPath, err)
}
if err := writeKey(file); err != nil {
return errors.Join(err, file.Abort())
}
// Flush before the rename, so a crash cannot leave an empty file where the
// previous export was.
if err := file.Sync(); err != nil {
return errors.Join(fmt.Errorf("flushing %s: %w", outPath, err), file.Abort())
}
if err := file.Close(); err != nil {
return fmt.Errorf("writing %s: %w", outPath, err)
}
return nil
}
// resolveSymlink returns the path a chain of symlinks ends at.
// filepath.EvalSymlinks cannot be used on the path as a whole: it fails when
// the last link points at a file that does not exist yet, and such a link
// still says where the key belongs. A path that cannot be inspected is
// returned unchanged, so that the caller's write reports the problem.
func resolveSymlink(path string) (string, error) {
for range maxSymlinkHops {
info, err := os.Lstat(path)
if err != nil || info.Mode()&os.ModeSymlink == 0 {
return path, nil
}
target, err := os.Readlink(path)
if err != nil {
return "", errView on GitHub (pinned to 329838acdf)
Solutions
- Check the wrapped errno: EBUSY/EXDEV/EPERM indicate the target cannot be renamed over — export to a different path
- If the target is a bind mount, write to a new file and remount/copy instead
- Verify you own the parent directory or have write+execute on it
- Retry after removing anything special about the target path (mount point, immutable flag: chattr -i)
Example fix
// before ipfs key export mykey -o /etc/config/identity.key # bind-mounted // after ipfs key export mykey -o /tmp/identity.key && cp /tmp/identity.key /etc/config/identity.key
Defensive patterns
Strategy: validation
Validate before calling
# ensure target is not a mount point / bind mount and parent is writable mountpoint -q "$out" && echo 'cannot rename over mount point' findmnt -T "$out"
Prevention
- Never target bind-mounted files or mount points directly with -o
- Ensure you have write permission on the parent directory (rename needs it)
- Avoid overlay/immutable-flagged targets; clear chattr +i if set
When it happens
Trigger: `ipfs key export -o <path>` where the target is a bind-mounted file, a mount point, or the parent directory disallows rename (sticky-bit/dir permission issues, cross-device conditions). Also close-time write-back errors on failing storage.
Common situations: Trying to overwrite a file that is a bind mount inside a container; exporting over a file in a directory with the sticky bit not owned by the user; overlayfs/docker volume edge cases where rename over the target fails.
Related errors
- refusing to export key to %s: not a regular file, character
- creating temporary file for %s: %w
- flushing %s: %w
- too many levels of symbolic links: %s
- refusing to export key to %s: it changed type while being op
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/bbe7be03b4fdc522.
Report an issue: GitHub.