PrefectHQ/fastmcp · error · ValueError

Query parameters {invalid_query_params} must be optional fun

Error message

Query parameters {invalid_query_params} must be optional function parameters with default values

What it means

RFC 6570 query parameters (?name={value}) are optional by nature - a client may omit them. To support omission, FastMCP requires every function parameter bound to a query parameter to have a default value. Required (no-default) parameters bound to the query section raise this error.

Source

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

        required_params = {
            p
            for p in func_params
            if user_sig.parameters[p].default is inspect.Parameter.empty
            and user_sig.parameters[p].kind != inspect.Parameter.VAR_KEYWORD
        }
        optional_params = {
            p
            for p in func_params
            if user_sig.parameters[p].default is not inspect.Parameter.empty
            and user_sig.parameters[p].kind != inspect.Parameter.VAR_KEYWORD
        }

        # Validate RFC 6570 query parameters
        # Query params must be optional (have defaults)
        if query_params:
            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}"
                )

View on GitHub (pinned to 1f02114297)

Solutions

  1. Give the query-bound function parameter a default value (e.g. limit: int = 10)
  2. Move the parameter into the URI path section if it must be required
  3. Remove the parameter from both the URI and the function if it isn't needed

Example fix

// before
def list_items(key: str, limit: int): ...
template(uri_template="items://{key}?limit={limit}")
// after
def list_items(key: str, limit: int = 10): ...
template(uri_template="items://{key}?limit={limit}")
Defensive patterns

Strategy: validation

Validate before calling

import inspect, re
def check_query_params(fn, uri_template):
    query = uri_template.split("?", 1)[-1]
    qparams = {p.replace("-", "_") for p in re.findall(r"\{(\w[-\w]*)\}", query)}
    sig = inspect.signature(fn)
    for name in qparams:
        p = sig.parameters.get(name)
        if p is None or p.default is inspect.Parameter.empty:
            raise TypeError(f"query param {name} needs a default value")

Type guard

def query_params_optional(fn, uri_template) -> bool:
    import inspect, re
    query = uri_template.split("?", 1)[-1]
    qp = {p.replace("-", "_") for p in re.findall(r"\{(\w[-\w]*)\}", query)}
    params = inspect.signature(fn).parameters
    return all(n in params and params[n].default is not inspect.Parameter.empty for n in qp)

Try / catch

try:
    tpl = FunctionResourceTemplate.from_function(fn, uri_template=uri)
except ValueError as e:
    if "must be optional" in str(e):
        fn = add_defaults(fn)  # bind defaults for query-bound params
        tpl = FunctionResourceTemplate.from_function(fn, uri_template=uri)
    else:
        raise

Prevention

When it happens

Trigger: Registering a template where a parameter appearing only in the URI query part (e.g. ?limit={limit}) maps to a function parameter without a default, like def fn(key: str, limit: int).

Common situations: Adding an optional query filter but declaring the function param as required; moving a parameter from the path to the query section without adding a default; stricter signatures after refactoring.

Related errors


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