{"record":{"id":"abfa680fcc514ece","repo":"PrefectHQ/fastmcp","slug":"required-function-arguments-required-params-must","errorCode":null,"errorMessage":"Required function arguments {required_params} must be a subset of the URI path parameters {path_params}","messagePattern":"Required function arguments (.+?) must be a subset of the URI path parameters (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/resources/template.py","lineNumber":522,"sourceCode":"        optional_params = {\n            p\n            for p in func_params\n            if user_sig.parameters[p].default is not inspect.Parameter.empty\n            and user_sig.parameters[p].kind != inspect.Parameter.VAR_KEYWORD\n        }\n\n        # Validate RFC 6570 query parameters\n        # Query params must be optional (have defaults)\n        if query_params:\n            invalid_query_params = query_params - optional_params\n            if invalid_query_params:\n                raise ValueError(\n                    f\"Query parameters {invalid_query_params} must be optional function parameters with default values\"\n                )\n\n        # Check if required parameters are a subset of the path parameters\n        if not required_params.issubset(path_params):\n            raise ValueError(\n                f\"Required function arguments {required_params} must be a subset of the URI path parameters {path_params}\"\n            )\n\n        # Check if all URI parameters are valid function parameters (skip if **kwargs present)\n        if not any(\n            param.kind == inspect.Parameter.VAR_KEYWORD\n            for param in sig.parameters.values()\n        ):\n            if not all_uri_params.issubset(func_params):\n                raise ValueError(\n                    f\"URI parameters {all_uri_params} must be a subset of the function arguments: {func_params}\"\n                )\n\n        description = description if description is not None else inspect.getdoc(fn)\n\n        # if the fn is a callable class, we need to get the __call__ method from here out\n        if not inspect.isroutine(fn) and not isinstance(fn, functools.partial):\n            fn = fn.__call__","sourceCodeStart":504,"sourceCodeEnd":540,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/resources/template.py#L504-L540","documentation":"Required function parameters (no default) must be satisfiable from the URI path, because path parameters are always present when the template matches. If a required parameter isn't in the path, there is no guaranteed source for it (query params are optional), so registration fails.","triggerScenarios":"Registering a template where a required function parameter appears neither in the path placeholders nor with a default - e.g. def fn(key: str, locale: str) with uri_template=\"data://{key}\".","commonSituations":"Forgetting to include a parameter in the URI template after adding it to the function; copy-pasting a function from another template; server-injected params misread as user-facing (those are excluded automatically).","solutions":["Add the parameter to the URI path: uri_template=\"data://{key}/{locale}\"","Give the parameter a default value and (optionally) expose it as a query parameter","Remove the parameter from the function signature if it's unused"],"exampleFix":"// before\ndef get(key: str, locale: str): ...\nResourceTemplate.from_function(get, uri_template=\"data://{key}\")\n// after\ndef get(key: str, locale: str = \"en\"): ...\nResourceTemplate.from_function(get, uri_template=\"data://{key}?locale={locale}\")","handlingStrategy":"validation","validationCode":"import inspect, re\ndef check_required_in_path(fn, uri_template):\n    path = uri_template.split(\"?\", 1)[0]\n    path_params = {p.replace(\"-\", \"_\") for p in re.findall(r\"\\{(\\w[-\\w]*)\\}\", path)}\n    required = {n for n, p in inspect.signature(fn).parameters.items()\n                if p.default is inspect.Parameter.empty\n                and p.kind in (inspect.Parameter.POSITIONAL_OR_KEYWORD, inspect.Parameter.KEYWORD_ONLY)}\n    if not required <= path_params:\n        raise TypeError(f\"required {required - path_params} missing from path\")","typeGuard":"def required_in_path(fn, uri_template) -> bool:\n    import inspect, re\n    path = uri_template.split(\"?\", 1)[0]\n    pp = {p.replace(\"-\", \"_\") for p in re.findall(r\"\\{(\\w[-\\w]*)\\}\", path)}\n    req = {n for n, p in inspect.signature(fn).parameters.items()\n           if p.default is inspect.Parameter.empty}\n    return req <= pp","tryCatchPattern":"try:\n    tpl = FunctionResourceTemplate.from_function(fn, uri_template=uri)\nexcept ValueError as e:\n    if \"must be a subset of the URI path\" in str(e):\n        raise TypeError(f\"Add missing path placeholders to {uri!r} or give the params defaults\") from e\n    raise","preventionTips":["Design templates so required params are always in the path","Give defaults to anything not in the path","Add a registration test per template that mirrors these subset checks"],"tags":["uri-template","validation","signature"],"backgroundTag":"required-parameter-unbound","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}