{"record":{"id":"76d306a721c315a4","repo":"restic/restic","slug":"unexpected-file-type-v-at-q","errorCode":null,"errorMessage":"unexpected file type %v at %q","messagePattern":"unexpected file type (.+?) at %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/restorer/fileswriter.go","lineNumber":77,"sourceCode":"\t\tbuckets:              buckets,\n\t\tallowRecursiveDelete: allowRecursiveDelete,\n\t\tcache:                cache,\n\t}\n}\n\nfunc openFile(path string) (*os.File, error) {\n\tf, err := fs.OpenFile(path, fs.O_WRONLY|fs.O_NOFOLLOW, 0600)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tfi, err := f.Stat()\n\tif err != nil {\n\t\t_ = f.Close()\n\t\treturn nil, err\n\t}\n\tif !fi.Mode().IsRegular() {\n\t\t_ = f.Close()\n\t\treturn nil, fmt.Errorf(\"unexpected file type %v at %q\", fi.Mode().Type(), path)\n\t}\n\treturn f, nil\n}\n\nfunc createFile(path string, createSize int64, sparse bool, allowRecursiveDelete bool) (*os.File, error) {\n\tf, err := fs.OpenFile(path, fs.O_CREATE|fs.O_WRONLY|fs.O_NOFOLLOW, 0600)\n\tif err != nil && fs.IsAccessDenied(err) {\n\t\t// If file is readonly, clear the readonly flag by resetting the\n\t\t// permissions of the file and try again\n\t\t// as the metadata will be set again in the second pass and the\n\t\t// readonly flag will be applied again if needed.\n\t\tif err = fs.ResetPermissions(path); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif f, err = fs.OpenFile(path, fs.O_WRONLY|fs.O_NOFOLLOW, 0600); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t} else if err != nil && (errors.Is(err, syscall.ELOOP) || errors.Is(err, syscall.EISDIR)) {","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/restic/restic/blob/a80be1478a4c537f8396e0db2b05120aa78f11e0/internal/restorer/fileswriter.go#L59-L95","documentation":"openFile in the restorer opens an existing destination path with O_WRONLY|O_NOFOLLOW and 0600, then Stats it and refuses anything that is not a regular file; this error names the file type and path. FIFOs, device nodes, sockets and similar special files cannot receive restored file content. (Symlinks fail earlier at open with ELOOP because of O_NOFOLLOW; directories fail with EISDIR.) It fires during restore when the target path for a regular file is occupied by a special file.","triggerScenarios":"Restoring into a destination where a previous process created a named pipe, unix socket or device node at a path that is a regular file in the snapshot; on Windows, reserved device names (NUL, CON, COM1) used as filenames; container/VM images whose extraction created device nodes prematurely.","commonSituations":"Restoring over an unpacked rootfs image that contains /dev-like nodes; leftover chroot/container build trees; intentionally booby-trapped directories with FIFOs at file paths.","solutions":["Inspect the path: ls -l / stat on the reported target to see the special file type","Remove or relocate the special file, then restore again","Restore into a fresh, empty directory instead of over an existing tree"],"exampleFix":"# before\nrestic restore latest --target /srv/restore\n# after\nrm -f /srv/restore/var/run/notify.fifo   # the reported special file\nrestic restore latest --target /srv/restore","handlingStrategy":"validation","validationCode":"if fi, err := fs.Lstat(path); err == nil && !fi.Mode().IsRegular() {\n    return fmt.Errorf(\"refusing to restore over %s at %s — remove or move it first\", fi.Mode().Type(), path)\n}","typeGuard":"func isRegularFilePath(path string) bool {\n    fi, err := os.Lstat(path)\n    return err == nil && fi.Mode().IsRegular()\n}","tryCatchPattern":null,"preventionTips":["Restore into a fresh target directory when possible","Pre-clean destinations built from container/VM images that contain device nodes or FIFOs","On Windows, avoid restoring files named after reserved devices (NUL, CON, COM1)"],"tags":["go","restic","restore","filesystem","windows"],"backgroundTag":null,"analyzedSha":"a80be1478a4c537f8396e0db2b05120aa78f11e0","analyzedAt":"2026-08-15T15:30:29.928Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}