warpdotdev/warp · error · MergeError
config_not_regular_file
config_not_regular_file
Error message
config_not_regular_file
What it means
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.
Source
Thrown at resources/bundled/skills/tui-migrate-setup/scripts/merge_mcp_config.py:116
else:
document.clear()
document.update(value)
def _read_regular_file(path: Path, *, missing_ok: bool) -> tuple[bytes, int | None]:
try:
metadata = path.lstat()
except FileNotFoundError:
if missing_ok:
return b"", None
raise MergeError("source_config_unavailable")
except OSError as error:
raise MergeError("config_unavailable") from error
if stat.S_ISLNK(metadata.st_mode):
raise MergeError("config_symlink_rejected")
if not stat.S_ISREG(metadata.st_mode):
raise MergeError("config_not_regular_file")
if metadata.st_size > MAX_CONFIG_BYTES:
raise MergeError("config_too_large")
flags = os.O_RDONLY
if hasattr(os, "O_NOFOLLOW"):
flags |= os.O_NOFOLLOW
try:
descriptor = os.open(path, flags)
with os.fdopen(descriptor, "rb") as file:
raw = file.read(MAX_CONFIG_BYTES + 1)
except OSError as error:
raise MergeError("config_unavailable") from error
if len(raw) > MAX_CONFIG_BYTES:
raise MergeError("config_too_large")
return raw, stat.S_IMODE(metadata.st_mode)
def _decode_document(raw: bytes) -> dict[str, Any]:View on GitHub (pinned to e72fd7aacb)
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'
Example fix
# before python merge_mcp_config.py --source ~/.config/warp --destination ... # error: config_not_regular_file (~/.config/warp is a directory) # after python merge_mcp_config.py --source ~/.config/warp/mcp.json --destination ...
Defensive patterns
Strategy: validation
Validate before calling
import os, stat
for p in (source_path, destination_path):
if os.path.exists(p):
mode = os.lstat(p).st_mode
if not stat.S_ISREG(mode):
raise SystemExit(f'{p} is not a regular file') Type guard
def is_regular_file(path) -> bool:
import os, stat
try:
return stat.S_ISREG(os.lstat(path).st_mode)
except OSError:
return False Try / catch
if result.returncode != 0 and 'config_not_regular_file' in result.stderr:
# stat <path> — expect 'regular file'; otherwise append the filename or fix the mechanism
... Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- source_config_unavailable
- config_unavailable
- config_too_large
- settings_symlink_rejected
- config_symlink_rejected
AI-assisted analysis of warpdotdev/warp@e72fd7aacb (2026-08-16).
Data as JSON: /api/errors/25c390963ba64719.
Report an issue: GitHub.