PrefectHQ/fastmcp · error · ValueError

Functions with *args are not supported as resource templates

Error message

Functions with *args are not supported as resource templates

What it means

Resource templates map URI template parameters to function parameters. A *args parameter has no fixed name, so there is no way to bind URI parameters to it; the library rejects any function with a positional-varargs parameter at registration time. **kwargs is explicitly allowed because URI/query parameter names map into it by keyword.

Source

Thrown at fastmcp_slim/fastmcp/resources/template.py:456

        mime_type: str | None = None,
        tags: set[str] | None = None,
        annotations: Annotations | None = None,
        meta: dict[str, Any] | None = None,
        auth: AuthCheck | list[AuthCheck] | None = None,
        security: ResourceSecurity | None | InheritSecurity = INHERIT_SECURITY,
    ) -> FunctionResourceTemplate:
        """Create a template from a function."""

        func_name = name or getattr(fn, "__name__", None) or fn.__class__.__name__
        if func_name == "<lambda>":
            raise ValueError("You must provide a name for lambda functions")

        # Reject functions with *args
        # (**kwargs is allowed because the URI will define the parameter names)
        sig = inspect.signature(fn)
        for param in sig.parameters.values():
            if param.kind == inspect.Parameter.VAR_POSITIONAL:
                raise ValueError(
                    "Functions with *args are not supported as resource templates"
                )

        # Extract path and query parameters from URI template.
        # Allow hyphens in names and normalize to underscores so they
        # match Python function parameter names.
        raw_path_params = set(re.findall(r"{([\w-]+)(?:\*)?}", uri_template))
        raw_query_params = extract_query_params(uri_template)

        # Detect collisions: two raw param names that normalize to the
        # same Python identifier (e.g. {user-id} and {user_id}).
        all_raw = raw_path_params | raw_query_params
        seen: dict[str, str] = {}
        for raw_name in sorted(all_raw):
            normalized = raw_name.replace("-", "_")
            if normalized in seen:
                raise ValueError(
                    f"URI template parameters '{seen[normalized]}' and "

View on GitHub (pinned to 1f02114297)

Solutions

  1. Change the function to take explicit named parameters matching the URI template parameters
  2. Wrap the generic function in a named def whose parameters match the URI template
  3. If you truly need arbitrary params, accept **kwargs only (allowed) instead of *args

Example fix

// before
def handler(*args):
    return lookup(args[0])
ResourceTemplate.from_function(handler, uri_template="users://{user_id}")
// after
def handler(user_id: str):
    return lookup(user_id)
Defensive patterns

Strategy: validation

Validate before calling

import inspect
def ensure_no_varargs(fn):
    for p in inspect.signature(fn).parameters.values():
        if p.kind is inspect.Parameter.VAR_POSITIONAL:
            raise TypeError(f"{fn} uses *args; not allowed for templates")

Type guard

def template_safe(fn) -> bool:
    return not any(
        p.kind is inspect.Parameter.VAR_POSITIONAL
        for p in inspect.signature(fn).parameters.values()
    )

Try / catch

try:
    tpl = FunctionResourceTemplate.from_function(fn, uri_template=uri)
except ValueError as e:
    if "*args" in str(e):
        fn = wrap_with_named_params(fn, uri)
        tpl = FunctionResourceTemplate.from_function(fn, uri_template=uri)
    else:
        raise

Prevention

When it happens

Trigger: Calling ResourceTemplate.from_function with a def that declares *args (e.g. def fn(*args, **kwargs)) and a URI template.

Common situations: Reusing a generic dispatch/forwarding function as a template body; decorator-produced wrappers that accept *args, **kwargs; adapting an existing handler signature to the template API.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/c44d5f60f800b64c. Report an issue: GitHub.