{"record":{"id":"e307786c393524c1","repo":"junegunn/fzf","slug":"invalid-history-file-e-error","errorCode":null,"errorMessage":"invalid history file: ${e.Error()}","messagePattern":"invalid history file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/history.go","lineNumber":24,"sourceCode":"\t\"strings\"\n)\n\n// History struct represents input history\ntype History struct {\n\tpath     string\n\tlines    []string\n\tmodified map[int]string\n\tmaxSize  int\n\tcursor   int\n}\n\n// NewHistory returns the pointer to a new History struct\nfunc NewHistory(path string, maxSize int) (*History, error) {\n\tfmtError := func(e error) error {\n\t\tif os.IsPermission(e) {\n\t\t\treturn errors.New(\"permission denied: \" + path)\n\t\t}\n\t\treturn errors.New(\"invalid history file: \" + e.Error())\n\t}\n\n\t// Read history file\n\tdata, err := os.ReadFile(path)\n\tif err != nil {\n\t\t// If it doesn't exist, check if we can create a file with the name\n\t\tif os.IsNotExist(err) {\n\t\t\tdata = []byte{}\n\t\t\tif err := os.WriteFile(path, data, 0600); err != nil {\n\t\t\t\treturn nil, fmtError(err)\n\t\t\t}\n\t\t} else {\n\t\t\treturn nil, fmtError(err)\n\t\t}\n\t}\n\t// Split lines and limit the maximum number of lines\n\tlines := strings.Split(strings.Trim(string(data), \"\\n\"), \"\\n\")\n\tif len(lines[len(lines)-1]) > 0 {","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/junegunn/fzf/blob/bd4efa277b49ef34ca4025bff9b1a288e1980eff/src/history.go#L6-L42","documentation":"Returned by startHttpServer (src/server.go:102) when net.Listen('unix', address.sock) fails while creating the listener for fzf's --listen UNIX socket mode. This happens after the stale-socket check, so the file was either absent or just removed; the operating system itself refused to bind a UNIX domain socket at that path. The underlying errno is unfortunately not wrapped into the message.","triggerScenarios":"Calling fzf --listen /some/dir/fzf.sock where the parent directory does not exist, is not writable by the current user, or the path crosses a filesystem that disallows sockets (e.g. some NFS mounts, /proc, FAT). Also triggered when the path is too long (UNIX socket paths are limited to ~104-108 bytes) or a non-socket file system entry occupies the name in a way os.Stat/os.Remove could not clear (e.g. a directory with that exact name).","commonSituations":"Pointing --listen at a socket path inside a directory the user cannot write (e.g. /run/fzf.sock as non-root); a socket path on an NFS/overlay mount that returns EOPNOTSUPP or EACCES; typos in the directory part of the socket path; paths generated with long temp prefixes exceeding sun_path limits; containers where the chosen directory is read-only.","solutions":["Check that the socket's parent directory exists and is writable: `mkdir -p ~/.cache/fzf && [ -w ~/.cache/fzf ]`. Prefer $XDG_RUNTIME_DIR or $TMPDIR for socket paths.","Shorten the socket path if it is near 104+ characters; use something like /tmp/fzf.sock.","If the path is on NFS or a network/odd filesystem, move it to a local filesystem such as /tmp or /run/user/$(id -u).","If a non-socket entry (e.g. a directory) has the socket's name, remove or rename it: `rm -rf /path/fzf.sock` only if it is yours.","Re-run with strace (`strace -f -e trace=bind fzf --listen ...`) to capture the exact errno if the above does not resolve it."],"exampleFix":"# before\nfzf --listen /run/fzf/main-listener-socket.sock   # /run not writable, path too long\n\n# after\nmkdir -p \"${XDG_RUNTIME_DIR:-/tmp}/fzf\"\nfzf --listen \"${XDG_RUNTIME_DIR:-/tmp}/fzf/fzf.sock\"","handlingStrategy":"validation","validationCode":"// Go caller: verify the socket path is bindable before spawning fzf\nfunc canBindUnixSocket(sockPath string) bool {\n    if len(sockPath) >= 104 { // typical sun_path limit\n        return false\n    }\n    dir := filepath.Dir(sockPath)\n    info, err := os.Stat(dir)\n    if err != nil || !info.IsDir() {\n        return false\n    }\n    // probe writability by creating and removing a temp file in dir\n    f, err := os.CreateTemp(dir, \".probe-*\")\n    if err != nil {\n        return false\n    }\n    f.Close()\n    os.Remove(f.Name())\n    return true\n}","typeGuard":"func isUnixListenFailure(stderr string) bool {\n    return strings.Contains(stderr, \"failed to listen on \") &&\n        strings.HasSuffix(strings.TrimSpace(strings.Split(stderr, \"\\n\")[0]), \".sock\")\n}","tryCatchPattern":"// shell wrapper: fail with diagnostics instead of a bare fzf error\nif ! fzf --listen \"$SOCK\" 2>err.log; then\n    if grep -q \"failed to listen on $SOCK\" err.log; then\n        echo \"cannot bind $SOCK: check dir exists/writable, path length < 104, local fs\" >&2\n    fi\nfi","preventionTips":["Default socket paths to $XDG_RUNTIME_DIR or $TMPDIR, never arbitrary absolute dirs.","Keep socket paths short (< 104 bytes).","Avoid placing sockets on NFS/FAT/overlay mounts."],"tags":["go","unix-socket","fzf","filesystem","permissions"],"backgroundTag":null,"analyzedSha":"bd4efa277b49ef34ca4025bff9b1a288e1980eff","analyzedAt":"2026-08-15T06:11:46.983Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}