PrefectHQ/fastmcp · error · ValueError

URI parameters {all_uri_params} must be a subset of the func

Error message

URI parameters {all_uri_params} must be a subset of the function arguments: {func_params}

What it means

Every {param} in the URI template must correspond to a declared function parameter so values can be passed when the template matches. This check is skipped when the function has **kwargs, which absorbs any URI parameter by name. Otherwise a URI parameter with no matching function parameter raises this error.

Source

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

            invalid_query_params = query_params - optional_params
            if invalid_query_params:
                raise ValueError(
                    f"Query parameters {invalid_query_params} must be optional function parameters with default values"
                )

        # Check if required parameters are a subset of the path parameters
        if not required_params.issubset(path_params):
            raise ValueError(
                f"Required function arguments {required_params} must be a subset of the URI path parameters {path_params}"
            )

        # Check if all URI parameters are valid function parameters (skip if **kwargs present)
        if not any(
            param.kind == inspect.Parameter.VAR_KEYWORD
            for param in sig.parameters.values()
        ):
            if not all_uri_params.issubset(func_params):
                raise ValueError(
                    f"URI parameters {all_uri_params} must be a subset of the function arguments: {func_params}"
                )

        description = description if description is not None else inspect.getdoc(fn)

        # if the fn is a callable class, we need to get the __call__ method from here out
        if not inspect.isroutine(fn) and not isinstance(fn, functools.partial):
            fn = fn.__call__
        # if the fn is a staticmethod, we need to work with the underlying function
        if isinstance(fn, staticmethod):
            fn = fn.__func__

        # Transform Context type annotations to Depends() for unified DI
        fn = transform_context_annotations(fn)

        wrapper_fn = without_injected_parameters(fn)
        type_adapter = get_cached_typeadapter(wrapper_fn)
        parameters = type_adapter.json_schema()

View on GitHub (pinned to 1f02114297)

Solutions

  1. Add a function parameter with the same name as the URI placeholder
  2. Fix the URI template so its placeholders match the existing function parameters
  3. Accept **kwargs in the function if you intentionally want to absorb arbitrary URI params

Example fix

// before
def get(key: str): ...
ResourceTemplate.from_function(get, uri_template="data://{key}/{version}")
// after
def get(key: str, version: str): ...
ResourceTemplate.from_function(get, uri_template="data://{key}/{version}")
Defensive patterns

Strategy: validation

Validate before calling

import inspect, re
def check_uri_params_covered(fn, uri_template):
    allp = {p.replace("-", "_") for p in re.findall(r"\{(\w[-\w]*)\}", uri_template)}
    params = inspect.signature(fn).parameters
    has_kw = any(p.kind is inspect.Parameter.VAR_KEYWORD for p in params.values())
    if not has_kw and not allp <= set(params):
        raise TypeError(f"URI params {allp - set(params)} not in function")

Type guard

def uri_params_covered(fn, uri_template) -> bool:
    import inspect, re
    allp = {p.replace("-", "_") for p in re.findall(r"\{(\w[-\w]*)\}", uri_template)}
    params = inspect.signature(fn).parameters
    if any(p.kind is inspect.Parameter.VAR_KEYWORD for p in params.values()):
        return True
    return allp <= set(params)

Try / catch

try:
    tpl = FunctionResourceTemplate.from_function(fn, uri_template=uri)
except ValueError as e:
    if "must be a subset of the function arguments" in str(e):
        raise TypeError(f"Align {uri!r} placeholders with {fn.__name__} signature") from e
    raise

Prevention

When it happens

Trigger: Registering a template whose URI references a parameter the function doesn't declare (typo or leftover placeholder), and the function has no **kwargs.

Common situations: Renaming a function parameter without updating the URI template; editing the URI template by hand and adding a placeholder the function never accepted; case-sensitivity mismatches between URI and Python names.

Related errors


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