pytest-dev/pytest · error · UsageError

: config option ' ' expects a float, got

Error message

{self.inipath}: config option '{name}' expects a float, got {value_type}: {value!r}

What it means

Raised by pytest's TOML config parser when a 'float'-type ini option receives a non-numeric value. Integers are accepted (since int is in the accepted tuple), but booleans are explicitly rejected via `isinstance(value, bool)`. Strings are rejected.

Solutions

  1. Use an unquoted number: change `timeout = "60"` to `timeout = 60.0` or `timeout = 60`
  2. Replace true/false with the intended numeric value
  3. Ensure the value is a literal float or int, not a string expression

Example fix

// pyproject.toml — before
[tool.pytest.ini_options]
timeout = "60"

// after
[tool.pytest.ini_options]
timeout = 60.0
Defensive patterns

Strategy: validation

Validate before calling

import tomllib
with open('pyproject.toml', 'rb') as f:
    data = tomllib.load(f)
opts = data.get('tool', {}).get('pytest', {}).get('ini_options', {})
for key, val in opts.items():
    if isinstance(val, str):
        print(f"{key}: got string {val!r}, consider unquoted number if type is 'float'")
    elif isinstance(val, bool):
        print(f"{key}: got bool, but float type rejects bool")

Type guard

def is_toml_number_not_bool(value: object) -> bool:
    return isinstance(value, (int, float)) and not isinstance(value, bool)

Prevention

When it happens

Trigger: An addini(type='float') option is set to a string or bool in pyproject.toml. Example: timeout = "60" (string) or timeout = true (bool) instead of timeout = 60.0 or timeout = 60. The check `not isinstance(value, (float, int)) or isinstance(value, bool)` triggers.

Common situations: Quoting a float (making it a string). Using true/false (bool) for a threshold. Assuming TOML coerces strings to numbers (it does not).

Related errors


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

Appendix: source

Thrown at src/_pytest/config/__init__.py:2012

            # Expect a boolean.
            if not isinstance(value, bool):
                raise TypeError(
                    f"{self.inipath}: config option '{name}' expects a bool, "
                    f"got {value_type}: {value!r}"
                )
            return value
        elif type == "int":
            # Expect an integer (but not bool, which is a subclass of int).
            if not isinstance(value, int) or isinstance(value, bool):
                raise TypeError(
                    f"{self.inipath}: config option '{name}' expects an int, "
                    f"got {value_type}: {value!r}"
                )
            return value
        elif type == "float":
            # Expect a float or integer only.
            if not isinstance(value, (float, int)) or isinstance(value, bool):
                raise TypeError(
                    f"{self.inipath}: config option '{name}' expects a float, "
                    f"got {value_type}: {value!r}"
                )
            return value
        elif type == "string":
            # Expect a string.
            if not isinstance(value, str):
                raise TypeError(
                    f"{self.inipath}: config option '{name}' expects a string, "
                    f"got {value_type}: {value!r}"
                )
            return value
        else:
            return self._getini_unknown_type(name, type, value)

    def _getconftest_pathlist(
        self, name: str, path: pathlib.Path
    ) -> list[pathlib.Path] | None:

View on GitHub (pinned to 0d6fbdeffa)