xtekky/gpt4free · error · ValueError

File must have .pa.py extension: {file_path}

Error message

File must have .pa.py extension: {file_path}

What it means

Raised by load_pa_provider when the file exists but its name does not end with '.pa.py'. The double extension is the convention that marks a file as a sandboxed PA provider; plain '.py' files are rejected so they cannot be confused with trusted code.

Source

Thrown at g4f/mcp/pa_provider.py:748

    with a ``create_completion`` or ``create_async_generator`` attribute is
    returned instead.

    Args:
        file_path: Path to the ``.pa.py`` file.

    Returns:
        The provider class, or ``None`` if none could be found.

    Raises:
        FileNotFoundError: If *file_path* does not exist.
        ValueError: If *file_path* does not end with ``.pa.py``.
        RuntimeError: If the file fails to execute.
    """
    file_path = Path(file_path)
    if not file_path.exists():
        raise FileNotFoundError(f"PA provider file not found: {file_path}")
    if not file_path.name.endswith(".pa.py"):
        raise ValueError(f"File must have .pa.py extension: {file_path}")

    code = file_path.read_text(encoding="utf-8")
    result = execute_safe_code(code, file_path=file_path, timeout=0.1, max_depth=100)

    if not result.success:
        raise RuntimeError(
            f"Failed to load PA provider from {file_path}:\n{result.error}"
        )

    # Prefer an explicit 'Provider' name
    provider_class = result.locals.get("Provider")
    if provider_class is not None:
        return provider_class

    # Fall back to any class that looks like a provider
    for obj in result.locals.values():
        if isinstance(obj, type) and (
            hasattr(obj, "create_completion") or hasattr(obj, "create_async_generator")

View on GitHub (pinned to 973504e177)

Solutions

  1. Rename the file to end in .pa.py (e.g. myprov.pa.py)
  2. Validate the suffix in your own tooling before calling load: p.name.endswith('.pa.py')

Example fix

# before
load_pa_provider(ws / 'myprov.py')

# after
load_pa_provider(ws / 'myprov.pa.py')
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
assert Path(file_path).name.endswith('.pa.py'), "PA providers must end in .pa.py"

Try / catch

try:
    provider_cls = load_pa_provider(path)
except ValueError:
    path = path.with_name(path.stem + '.pa.py')  # or reject the registration

Prevention

When it happens

Trigger: Passing 'myprov.py', 'provider.txt' or any file whose Path.name doesn't end with '.pa.py' to load_pa_provider.

Common situations: Renaming existing provider modules without adding the .pa.py suffix; automation that strips or rewrites extensions; copy-paste from examples that used plain .py files.

Related errors


AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14). Data as JSON: /api/errors/ec3581968fd421da. Report an issue: GitHub.