{"record":{"id":"c8c155aaec352b2e","repo":"kovidgoyal/kitty","slug":"failed-to-find-cwd-of-process-with-pid-pid","errorCode":null,"errorMessage":"Failed to find cwd of process with pid: {pid}","messagePattern":"Failed to find cwd of process with pid: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"kitty/child.py","lineNumber":86,"sourceCode":"            for p in pids:\n                with suppress(Exception):\n                    total += _memory_of_process(p)\n            return total\n        return -1\nelse:\n\n    def cmdline_of_pid(pid: int) -> list[str]:\n        with open(f'/proc/{pid}/cmdline', 'rb') as f:\n            return list(filter(None, f.read().decode('utf-8').split('\\0')))\n\n    if is_freebsd:\n\n        def cwd_of_process(pid: int) -> str:\n            import subprocess\n\n            cp = subprocess.run(['pwdx', str(pid)], capture_output=True)\n            if cp.returncode != 0:\n                raise ValueError(f'Failed to find cwd of process with pid: {pid}')\n            ans = cp.stdout.decode('utf-8', 'replace').split()[1]\n            return os.path.realpath(ans, strict=True)\n    else:\n\n        def cwd_of_process(pid: int) -> str:\n            # We use realpath instead of readlink to match macOS behavior where\n            # the underlying OS API returns real paths.\n            ans = f'/proc/{pid}/cwd'\n            return os.path.realpath(ans, strict=True)\n\n    def _environ_of_process(pid: int) -> str:\n        with open(f'/proc/{pid}/environ', 'rb') as f:\n            return f.read().decode('utf-8')\n\n    def process_group_map() -> DefaultDict[int, list[int]]:\n        ans: DefaultDict[int, list[int]] = defaultdict(list)\n        for x in os.listdir('/proc'):\n            try:","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kitty/child.py#L68-L104","documentation":"On Linux, cwd_of_process shells out to `pwdx <pid>` and raises ValueError when pwdx exits non-zero, i.e. the process's working directory could not be determined (process gone, permission denied, or kernel restriction).","triggerScenarios":"Calling cwd_of_process for a pid that has exited, a zombie, a process owned by another user (pwdx fails without permission), or on systems where hidepid/ptrace restrictions apply.","commonSituations":"kitty resolving the cwd of the shell/child process for window inheritance or `neighbor` semantics after the child died, or in restricted multi-user environments lacking pwdx or permissions.","solutions":["Ensure pwdx is installed (part of procps)","Retry with a live pid; check the process still exists before calling","Run with sufficient permissions to inspect the target process","Catch ValueError and fall back to $HOME or the parent's cwd"],"exampleFix":"# before\ncwd = cwd_of_process(pid)\n# after\ntry:\n    cwd = cwd_of_process(pid)\nexcept (ValueError, FileNotFoundError):\n    cwd = os.path.expanduser('~')","handlingStrategy":"fallback","validationCode":"import os\npid_alive = os.path.exists(f'/proc/{pid}')\ncwd = cwd_of_process(pid) if pid_alive else fallback_dir","typeGuard":null,"tryCatchPattern":"try:\n    cwd = cwd_of_process(pid)\nexcept ValueError:\n    cwd = os.path.expanduser('~')","preventionTips":["Check the pid is alive before resolving cwd","Ensure pwdx (procps) is installed","Catch ValueError and degrade gracefully"],"tags":["kitty","process","cwd","pwdx","linux"],"backgroundTag":"process-cwd-lookup-failed","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}