google/python-fire · error · ValueError

FindExecutableOnPath({0},...) failed because first argument

Error message

FindExecutableOnPath({0},...) failed because first argument must not have a path.

What it means

FindExecutableOnPath only resolves bare executable names against PATH directories; if the first argument contains a directory component (os.path.dirname is non-empty), it raises ValueError because PATH search semantics do not apply to relative/absolute paths. Paths should be checked for existence directly instead.

Source

Thrown at fire/console/files.py:102

      platform specific extensions are used.
    allow_extensions: A boolean flag indicating whether extensions in the
      executable are allowed.

  Returns:
    The path of 'executable' (possibly with a platform-specific extension) if
    found and executable, None if not found.

  Raises:
    ValueError: if executable has a path or an extension, and extensions are
      not allowed, or if there's an internal error.
  """

  if not allow_extensions and os.path.splitext(executable)[1]:
    raise ValueError('FindExecutableOnPath({0},...) failed because first '
                     'argument must not have an extension.'.format(executable))

  if os.path.dirname(executable):
    raise ValueError('FindExecutableOnPath({0},...) failed because first '
                     'argument must not have a path.'.format(executable))

  if path is None:
    effective_path = _GetSystemPath()
  else:
    effective_path = path
  effective_pathext = (pathext if pathext is not None
                       else _PlatformExecutableExtensions(
                           platforms.OperatingSystem.Current()))

  return _FindExecutableOnPath(executable, effective_path,
                               effective_pathext)

View on GitHub (pinned to 716bbc23d7)

Solutions

  1. Pass only the executable name: FindExecutableOnPath('git').
  2. If you already have a full path, use os.path.exists/shutil.which on it directly instead of this function.
  3. Split off the directory and search only the basename if PATH resolution is genuinely needed.

Example fix

// before
FindExecutableOnPath('/usr/bin/git')
// after
if os.path.exists('/usr/bin/git'): use('/usr/bin/git')
else: exe = FindExecutableOnPath('git')
Defensive patterns

Strategy: validation

Validate before calling

import os
if os.path.dirname(executable):
    if os.path.exists(executable):
        resolved = executable  # use directly, skip PATH search
    else:
        raise SystemExit(f'not found: {executable}')

Type guard

def is_bare_name(name: str) -> bool:
    return os.path.dirname(name) == ''

Try / catch

try:
    exe = files.FindExecutableOnPath(executable)
except ValueError as e:
    print(f'{e} — pass a name without directory components'); sys.exit(2)

Prevention

When it happens

Trigger: FindExecutableOnPath('/usr/bin/git') or FindExecutableOnPath('./tools/git') — any executable argument containing '/' or a drive/directory prefix.

Common situations: Users copying a full path where the API expects a name; conflating PATH lookup with local file resolution; building commands from config that stores full paths.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of google/python-fire@716bbc23d7 (2026-08-28). Data as JSON: /api/errors/82277956057521f7. Report an issue: GitHub.