{"record":{"id":"b157df919b3860c5","repo":"ipfs/kubo","slug":"refusing-to-export-key-to-s-not-a-regular-file","errorCode":null,"errorMessage":"refusing to export key to %s: not a regular file, character device or pipe","messagePattern":"refusing to export key to (.+?): not a regular file, character device or pipe","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/commands/keystore.go","lineNumber":355,"sourceCode":"\t\t\t\treturn err\n\t\t\t}\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"unrecognized export format: %s\", exportFormat)\n\t\t}\n\t\treturn nil\n\t}\n\n\t// Stat resolves symlinks: -o /dev/stdout is a link into /proc/self/fd.\n\tinfo, err := os.Stat(outPath)\n\tif err != nil && !errors.Is(err, os.ErrNotExist) {\n\t\treturn err\n\t}\n\tif err == nil {\n\t\tif info.Mode()&inPlaceModes != 0 {\n\t\t\treturn writeExportedKeyInPlace(outPath, writeKey)\n\t\t}\n\t\tif !info.Mode().IsRegular() {\n\t\t\treturn fmt.Errorf(\"refusing to export key to %s: not a regular file, character device or pipe\", outPath)\n\t\t}\n\t}\n\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","sourceCodeStart":337,"sourceCodeEnd":373,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/commands/keystore.go#L337-L373","documentation":"writeExportedKey only writes exported private keys to three kinds of targets: regular files (atomically, via temp file + rename), character devices, and named pipes (written in place). If the output path exists but is something else — a directory, a unix socket, a block device, etc. — the export is refused rather than failing obscurely later. This is a deliberate safety refusal: keys must not be 'written' into targets that cannot hold them.","triggerScenarios":"`ipfs key export <name> -o /some/existing/directory`; `-o /path/to/unix.sock`; `-o` pointing at a block device or other special file. os.Stat succeeded and the mode did not match regular/char-device/pipe.","commonSituations":"Forgetting the output filename and passing a directory; a stale socket file at the target path; shell variable expanding empty so `-o` gets a wrong value; mount points or special files on /dev.","solutions":["Pass a path to a regular file (existing or not), not a directory or socket","If targeting a directory, append the intended filename: `-o /dir/mykey.pem`","Check what is at the path: `ls -la <path>` / `stat <path>` and remove or rename the non-regular object","If you wanted stdout, omit `-o` or use a pipe/character device like /dev/stdout"],"exampleFix":"// before\nipfs key export mykey -o /tmp/keys   # directory\n// after\nipfs key export mykey -o /tmp/keys/mykey.pem","handlingStrategy":"validation","validationCode":"import os\nmode = os.lstat(out_path).st_mode\nif not (stat.S_ISREG(mode) or stat.S_ISCHR(mode) or stat.S_ISFIFO(mode)):\n    raise ValueError(f\"refusing export target {out_path}: not a regular file, char device or pipe\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass a full file path (including filename) to -o, never a directory","Run `stat <path>` before exporting to an existing path","Reserve dedicated directories for key exports to avoid stray sockets/special files"],"tags":["cli","keystore","filesystem","validation"],"backgroundTag":"invalid-output-target-type","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"}