pytest-dev/pytest · error · TypeError

mode {mode!r} must be an integer

Error message

mode {mode!r} must be an integer

What it means

Raised by LocalPath.chmod() when the mode argument is not an int. The method delegates to os.chmod, which requires a numeric permission bitmask (e.g. 0o755). Passing a string like '755' or 'rwxr-xr-x' is rejected with a TypeError before any filesystem call.

Source

Thrown at src/_pytest/_py/path.py:1039

    def atime(self):
        """Return last access time of the path."""
        return self.stat().atime

    def __repr__(self):
        return f"local({self.strpath!r})"

    def __str__(self):
        """Return string representation of the Path."""
        return self.strpath

    def chmod(self, mode, rec=0):
        """Change permissions to the given mode. If mode is an
        integer it directly encodes the os-specific modes.
        if rec is True perform recursively.
        """
        if not isinstance(mode, int):
            raise TypeError(f"mode {mode!r} must be an integer")
        if rec:
            for x in self.visit(rec=rec):
                error.checked_call(os.chmod, str(x), mode)
        error.checked_call(os.chmod, self.strpath, mode)

    def pypkgpath(self):
        """Return the Python package path by looking for the last
        directory upwards which still contains an __init__.py.
        Return None if a pkgpath cannot be determined.
        """
        pkgpath = None
        for parent in self.parts(reverse=True):
            if parent.isdir():
                if not parent.join("__init__.py").exists():
                    break
                if not isimportable(parent.basename):
                    break
                pkgpath = parent

View on GitHub (pinned to 0d6fbdeffa)

Solutions

  1. Pass an integer octal literal: path.chmod(0o755).
  2. Convert config strings: path.chmod(int(mode_str, 8)).
  3. Validate the mode is an int before calling.

Example fix

// before
p.chmod('755')
// after
p.chmod(0o755)
Defensive patterns

Strategy: validation

Validate before calling

def safe_chmod(path, mode):
    if isinstance(mode, str):
        mode = int(mode, 8)
    if not isinstance(mode, int):
        raise TypeError('mode must be int or octal string')
    path.chmod(mode)

Type guard

def is_int_mode(mode) -> bool:
    return isinstance(mode, int) and not isinstance(mode, bool)

Prevention

When it happens

Trigger: Calling path.chmod('755'); passing an octal literal as a string; passing None or a permission object instead of an int.

Common situations: Config-driven code that reads permission strings from YAML/ENV; shell-script-to-Python porting where chmod accepted string modes; forgetting the 0o prefix.

Related errors


AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11). Data as JSON: /api/errors/bcd57bdfc8ef3007. Report an issue: GitHub.