google/python-fire · error · ValueError
Fire can only be called on .py files.
Error message
Fire can only be called on .py files.
What it means
fire.import_module accepts either an existing path or a dotted module name. If the argument exists on disk but does not end in .py, fire first tries to interpret it as a module name; when that also raises ImportError, it gives up with ValueError('Fire can only be called on .py files.'). It deliberately restricts file-based loading to .py because importlib.util.spec_from_file_location requires .py files.
Source
Thrown at fire/__main__.py:102
Args:
module_or_filename (str): string name of path or module.
Raises:
ValueError: if the given file is invalid.
IOError: if the file or module can not be found or imported.
Returns:
Tuple[ModuleType, str]: returns the imported module and the module name,
usually extracted from the path itself.
"""
if os.path.exists(module_or_filename):
# importlib.util.spec_from_file_location requires .py
if not module_or_filename.endswith('.py'):
try: # try as module instead
return import_from_module_name(module_or_filename)
except ImportError:
raise ValueError('Fire can only be called on .py files.')
return import_from_file_path(module_or_filename)
if os.path.sep in module_or_filename: # Use / to detect if it was a filename.
raise OSError('Fire was passed a filename which could not be found.')
return import_from_module_name(module_or_filename) # Assume it's a module.
def main(args):
"""Entrypoint for fire when invoked as a module with python -m fire."""
if len(args) < 2:
print(cli_string)
sys.exit(1)
module_or_filename = args[1]
module, module_name = import_module(module_or_filename)View on GitHub (pinned to 716bbc23d7)
Solutions
- Rename the target so it ends in .py.
- If the target is a module inside a package, use the dotted module name: `python -m fire mypkg.mymodule`.
- If the target is not Python at all, invoke fire from within a Python entry point instead of passing the file to python -m fire.
Example fix
// before python -m fire ./tools/backup serve // after python -m fire tools/backup.py serve # or: python -m fire tools.backup serve
Defensive patterns
Strategy: validation
Validate before calling
import os
arg = './tools/backup'
if os.path.exists(arg) and not arg.endswith('.py'):
raise SystemExit('Fire file targets must end in .py; use a dotted module name otherwise') Type guard
def is_py_file_target(arg: str) -> bool:
return os.path.exists(arg) and arg.endswith('.py') Try / catch
try:
module, name = fire_import.import_module(arg)
except ValueError as e:
print(f'{arg}: {e} — rename to .py or pass pkg.mod'); sys.exit(2) Prevention
- Ensure all CLI entry scripts end in .py.
- For packages, pass dotted module names (pkg.mod), not paths.
- Do not pass shell scripts or configs to python -m fire.
When it happens
Trigger: python -m fire <existing-non-py-path> where the path exists, lacks the .py extension, and is not importable as a dotted module — e.g. `python -m fire ./serve.sh` or a directory-style path to a non-Python file.
Common situations: Passing shell scripts, config files, or extensionless executables to fire; forgetting to rename a Python file that was saved without the .py extension.
Related errors
- Unable to load module from specified path.
- Given file path does not exist.
- Fire was passed a filename which could not be found.
- The command argument must be a string or a sequence of argum
- 2
AI-assisted analysis of google/python-fire@716bbc23d7 (2026-08-28).
Data as JSON: /api/errors/dda4a280e168f95c.
Report an issue: GitHub.