{"record":{"id":"f8b28b4fa7804db3","repo":"ipfs/kubo","slug":"flushing-s-w","errorCode":null,"errorMessage":"flushing %s: %w","messagePattern":"flushing (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/commands/keystore.go","lineNumber":376,"sourceCode":"\n\t// The key is written next to the target and renamed over it, so replace\n\t// what a symlink points at rather than the symlink itself.\n\toutPath, err = resolveSymlink(outPath)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tfile, err := atomicfile.New(outPath, exportedKeyFileMode)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"creating temporary file for %s: %w\", outPath, err)\n\t}\n\tif err := writeKey(file); err != nil {\n\t\treturn errors.Join(err, file.Abort())\n\t}\n\t// Flush before the rename, so a crash cannot leave an empty file where the\n\t// previous export was.\n\tif err := file.Sync(); err != nil {\n\t\treturn errors.Join(fmt.Errorf(\"flushing %s: %w\", outPath, err), file.Abort())\n\t}\n\tif err := file.Close(); err != nil {\n\t\treturn fmt.Errorf(\"writing %s: %w\", outPath, err)\n\t}\n\treturn nil\n}\n\n// resolveSymlink returns the path a chain of symlinks ends at.\n// filepath.EvalSymlinks cannot be used on the path as a whole: it fails when\n// the last link points at a file that does not exist yet, and such a link\n// still says where the key belongs. A path that cannot be inspected is\n// returned unchanged, so that the caller's write reports the problem.\nfunc resolveSymlink(path string) (string, error) {\n\tfor range maxSymlinkHops {\n\t\tinfo, err := os.Lstat(path)\n\t\tif err != nil || info.Mode()&os.ModeSymlink == 0 {\n\t\t\treturn path, nil\n\t\t}","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/commands/keystore.go#L358-L394","documentation":"After writing the exported key into the temp file, writeExportedKey calls file.Sync() to flush it to stable storage before the atomic rename, so a crash can never leave an empty or truncated key file. This error joins the fsync failure with the temp file's Abort. It indicates an I/O-layer problem persisting the data, not a key-format problem.","triggerScenarios":"`ipfs key export` to a filesystem whose fsync fails: disk errors, some network filesystems (NFS oddities), full journal, or exporting onto virtual filesystems that do not support fsync (certain fuse mounts, /proc-like fs).","commonSituations":"Exporting to a flaky USB drive or failing disk; fuse/network mounts with unreliable fsync; container storage drivers with fsync quirks.","solutions":["Check the wrapped errno: EIO usually means failing hardware — run fsck or replace the disk","Retry the export to a different filesystem (e.g. local disk instead of a network mount)","The temp file was aborted, so no partial file remains — re-run once hardware/fs is healthy","Avoid exporting directly onto fuse/network filesystems known to reject fsync"],"exampleFix":"// before\nipfs key export mykey -o /mnt/flaky-nfs/mykey.pem\n// after\nipfs key export mykey -o /root/mykey.pem && cp /root/mykey.pem /mnt/flaky-nfs/","handlingStrategy":"retry","validationCode":"// Prefer local, fsync-capable filesystems for key export\nmount | grep \"$(df --output=target \"$(dirname \"$out\")\" | tail -1)\"  # avoid nfs/fuse targets","typeGuard":null,"tryCatchPattern":"if err := writeExportedKey(outPath, r, fmt); err != nil && strings.Contains(err.Error(), \"flushing\") {\n    // transient fsync failure: retry once on a local filesystem\n    return retryExport(outPath, r, fmt)\n}","preventionTips":["Export keys to local disk first, then transfer","Watch SMART/dmesg for disk errors after this error","Avoid fuse/network filesystems with known fsync issues for sensitive writes"],"tags":["cli","keystore","filesystem","fsync","io"],"backgroundTag":"fsync-failed","analyzedSha":"329838acdfafae224582930457efe80aa217afc0","analyzedAt":"2026-09-03T18:30:52.135Z","contentChangedAt":"2026-09-03T18:30:52.135Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}