{"record":{"id":"25c390963ba64719","repo":"warpdotdev/warp","slug":"config-not-regular-file","errorCode":"config_not_regular_file","errorMessage":"config_not_regular_file","messagePattern":"config_not_regular_file","errorType":"exception","errorClass":"MergeError","httpStatus":null,"severity":"error","filePath":"resources/bundled/skills/tui-migrate-setup/scripts/merge_mcp_config.py","lineNumber":116,"sourceCode":"    else:\n        document.clear()\n        document.update(value)\n\n\ndef _read_regular_file(path: Path, *, missing_ok: bool) -> tuple[bytes, int | None]:\n    try:\n        metadata = path.lstat()\n    except FileNotFoundError:\n        if missing_ok:\n            return b\"\", None\n        raise MergeError(\"source_config_unavailable\")\n    except OSError as error:\n        raise MergeError(\"config_unavailable\") from error\n\n    if stat.S_ISLNK(metadata.st_mode):\n        raise MergeError(\"config_symlink_rejected\")\n    if not stat.S_ISREG(metadata.st_mode):\n        raise MergeError(\"config_not_regular_file\")\n    if metadata.st_size > MAX_CONFIG_BYTES:\n        raise MergeError(\"config_too_large\")\n\n    flags = os.O_RDONLY\n    if hasattr(os, \"O_NOFOLLOW\"):\n        flags |= os.O_NOFOLLOW\n    try:\n        descriptor = os.open(path, flags)\n        with os.fdopen(descriptor, \"rb\") as file:\n            raw = file.read(MAX_CONFIG_BYTES + 1)\n    except OSError as error:\n        raise MergeError(\"config_unavailable\") from error\n    if len(raw) > MAX_CONFIG_BYTES:\n        raise MergeError(\"config_too_large\")\n    return raw, stat.S_IMODE(metadata.st_mode)\n\n\ndef _decode_document(raw: bytes) -> dict[str, Any]:","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/warpdotdev/warp/blob/e72fd7aacbbb2236d9b3be2aad7e7178fe94b4bc/resources/bundled/skills/tui-migrate-setup/scripts/merge_mcp_config.py#L98-L134","documentation":"After the symlink check, _read_regular_file() requires st_mode to be a regular file (S_ISREG); FIFOs, unix sockets, device nodes, and directories all raise config_not_regular_file. The tool reads with a byte cap and preserves/sets the file mode, which only has defined semantics for regular files.","triggerScenarios":"Passing a directory as --source or --destination (path typo that lands on a folder); a config 'file' that is actually a named pipe created by some sync tool; a device node accidentally referenced.","commonSituations":"Paths that omit the filename and hit its directory; exotic setups where config is fed through a socket/FIFO; /dev or /proc paths mistakenly used.","solutions":["Point the argument at the actual file inside the directory — add the filename","If the path is a pipe/socket, replace the mechanism with a regular file the tool can atomically rewrite","Confirm with stat <path>: the output should say 'regular file'"],"exampleFix":"# before\npython merge_mcp_config.py --source ~/.config/warp --destination ...\n# error: config_not_regular_file  (~/.config/warp is a directory)\n\n# after\npython merge_mcp_config.py --source ~/.config/warp/mcp.json --destination ...","handlingStrategy":"validation","validationCode":"import os, stat\n\nfor p in (source_path, destination_path):\n    if os.path.exists(p):\n        mode = os.lstat(p).st_mode\n        if not stat.S_ISREG(mode):\n            raise SystemExit(f'{p} is not a regular file')","typeGuard":"def is_regular_file(path) -> bool:\n    import os, stat\n    try:\n        return stat.S_ISREG(os.lstat(path).st_mode)\n    except OSError:\n        return False","tryCatchPattern":"if result.returncode != 0 and 'config_not_regular_file' in result.stderr:\n    # stat <path> — expect 'regular file'; otherwise append the filename or fix the mechanism\n    ...","preventionTips":["Always pass full file paths, not their directories","stat-check config paths in setup scripts","Do not feed FIFO/socket-based config feeds into the merge"],"tags":["filesystem","type-validation","config"],"backgroundTag":null,"analyzedSha":"e72fd7aacbbb2236d9b3be2aad7e7178fe94b4bc","analyzedAt":"2026-08-16T08:27:25.381Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}