python/cpython · error · TypeError
integer argument expected, got float
Error message
integer argument expected, got float
What it means
Raised by FileIO.__init__ when the file argument is a float. Because bool is a subclass of int and floats are not accepted as file descriptors, the constructor explicitly rejects float before the int fd handling path (note the bool special case that only draws a RuntimeWarning, whereas float is a hard TypeError).
Source
Thrown at Lib/_pyio.py:1546
writing.
A custom opener can be used by passing a callable as *opener*.
The underlying file descriptor for the file object is then obtained
by calling opener with (*name*, *flags*). *opener* must return
an open file descriptor (passing os.open as *opener* results in
functionality similar to passing None).
"""
if self._fd >= 0:
# Have to close the existing file first.
self._stat_atopen = None
try:
if self._closefd:
os.close(self._fd)
finally:
self._fd = -1
if isinstance(file, float):
raise TypeError('integer argument expected, got float')
if isinstance(file, int):
if isinstance(file, bool):
import warnings
warnings.warn("bool is used as a file descriptor",
RuntimeWarning, stacklevel=2)
file = int(file)
fd = file
if fd < 0:
raise ValueError('negative file descriptor')
else:
fd = -1
if not isinstance(mode, str):
raise TypeError('invalid mode: %s' % (mode,))
if not set(mode) <= set('xrwab+'):
raise ValueError('invalid mode: %s' % (mode,))
if sum(c in 'rwax' for c in mode) != 1 or mode.count('+') > 1:
raise ValueError('Must have exactly one of create/read/write/append 'View on GitHub (pinned to bc6749cc3b)
Solutions
- Pass an int file descriptor or a str/bytes/os.PathLike path, never a float
- Coerce numeric config values before use: fd = int(fd) after verifying it is integral
- If the value is really a path, make sure it stays a string (check for accidental str(fd) vs fd mix-ups)
Example fix
# before fd = json_config['fd'] # arrived as 3.0 f = open(fd, 'rb') # TypeError: integer argument expected, got float # after fd = int(json_config['fd']) f = open(fd, 'rb')
Defensive patterns
Strategy: type-guard
Validate before calling
import numbers
def normalize_fd(file):
if isinstance(file, float):
if file.is_integer():
return int(file)
raise TypeError('integer argument expected, got float')
return file
f = open(normalize_fd(file_arg), 'rb') Type guard
def is_fd_or_path(f):
return isinstance(f, (str, bytes, os.PathLike)) or (isinstance(f, int) and not isinstance(f, (bool, float)) and f >= 0) Try / catch
try:
f = open(file_arg, 'rb')
except TypeError as e:
if 'float' in str(e):
f = open(int(file_arg), 'rb')
else:
raise Prevention
- Keep fds as int; avoid float arithmetic on fd variables
- Validate externally sourced fds (JSON/YAML) with isinstance(x, int)
- Use None, not -1 or 0.0, as the 'no fd yet' sentinel
When it happens
Trigger: open(3.0, 'rb') or io.FileIO(2.5); passing a value computed with float arithmetic (e.g. os.dup results passed through float(), or division like fd/1) where a file descriptor integer or a path was expected.
Common situations: fd variables accidentally converted to float by numeric pipelines (numpy scalars of dtype float are also rejected differently, but plain Python float hits this exact branch); typos where a path string was replaced by a numeric variable; JSON-parsed config in which the fd arrived as 3.0 instead of 3.
Related errors
- negative file descriptor
- invalid mode: %s
- expected integer from opener
- an integer is required
- Must have exactly one of create/read/write/append mode and a
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/990e3663d802af6f.
Report an issue: GitHub.