{"record":{"id":"c44d5f60f800b64c","repo":"PrefectHQ/fastmcp","slug":"functions-with-args-are-not-supported-as-resource","errorCode":null,"errorMessage":"Functions with *args are not supported as resource templates","messagePattern":"Functions with \\*args are not supported as resource templates","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/resources/template.py","lineNumber":456,"sourceCode":"        mime_type: str | None = None,\n        tags: set[str] | None = None,\n        annotations: Annotations | None = None,\n        meta: dict[str, Any] | None = None,\n        auth: AuthCheck | list[AuthCheck] | None = None,\n        security: ResourceSecurity | None | InheritSecurity = INHERIT_SECURITY,\n    ) -> FunctionResourceTemplate:\n        \"\"\"Create a template from a function.\"\"\"\n\n        func_name = name or getattr(fn, \"__name__\", None) or fn.__class__.__name__\n        if func_name == \"<lambda>\":\n            raise ValueError(\"You must provide a name for lambda functions\")\n\n        # Reject functions with *args\n        # (**kwargs is allowed because the URI will define the parameter names)\n        sig = inspect.signature(fn)\n        for param in sig.parameters.values():\n            if param.kind == inspect.Parameter.VAR_POSITIONAL:\n                raise ValueError(\n                    \"Functions with *args are not supported as resource templates\"\n                )\n\n        # Extract path and query parameters from URI template.\n        # Allow hyphens in names and normalize to underscores so they\n        # match Python function parameter names.\n        raw_path_params = set(re.findall(r\"{([\\w-]+)(?:\\*)?}\", uri_template))\n        raw_query_params = extract_query_params(uri_template)\n\n        # Detect collisions: two raw param names that normalize to the\n        # same Python identifier (e.g. {user-id} and {user_id}).\n        all_raw = raw_path_params | raw_query_params\n        seen: dict[str, str] = {}\n        for raw_name in sorted(all_raw):\n            normalized = raw_name.replace(\"-\", \"_\")\n            if normalized in seen:\n                raise ValueError(\n                    f\"URI template parameters '{seen[normalized]}' and \"","sourceCodeStart":438,"sourceCodeEnd":474,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/resources/template.py#L438-L474","documentation":"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.","triggerScenarios":"Calling ResourceTemplate.from_function with a def that declares *args (e.g. def fn(*args, **kwargs)) and a URI template.","commonSituations":"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.","solutions":["Change the function to take explicit named parameters matching the URI template parameters","Wrap the generic function in a named def whose parameters match the URI template","If you truly need arbitrary params, accept **kwargs only (allowed) instead of *args"],"exampleFix":"// before\ndef handler(*args):\n    return lookup(args[0])\nResourceTemplate.from_function(handler, uri_template=\"users://{user_id}\")\n// after\ndef handler(user_id: str):\n    return lookup(user_id)","handlingStrategy":"validation","validationCode":"import inspect\ndef ensure_no_varargs(fn):\n    for p in inspect.signature(fn).parameters.values():\n        if p.kind is inspect.Parameter.VAR_POSITIONAL:\n            raise TypeError(f\"{fn} uses *args; not allowed for templates\")","typeGuard":"def template_safe(fn) -> bool:\n    return not any(\n        p.kind is inspect.Parameter.VAR_POSITIONAL\n        for p in inspect.signature(fn).parameters.values()\n    )","tryCatchPattern":"try:\n    tpl = FunctionResourceTemplate.from_function(fn, uri_template=uri)\nexcept ValueError as e:\n    if \"*args\" in str(e):\n        fn = wrap_with_named_params(fn, uri)\n        tpl = FunctionResourceTemplate.from_function(fn, uri_template=uri)\n    else:\n        raise","preventionTips":["Avoid reusing generic *args dispatcher functions as template bodies","Unwrap decorator-generated wrappers with functools.wraps and explicit signatures","Use **kwargs instead of *args when you need name-based absorption"],"tags":["python","resources","signature"],"backgroundTag":"unsupported-function-signature","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}