PrefectHQ/fastmcp · error · PromptError

Error rendering prompt {self.name!r}: {e}

Error message

Error rendering prompt {self.name!r}: {e}

What it means

When the prompt's render function raises any exception that is not a FastMCPError, render() logs the full traceback and re-raises it wrapped in a PromptError, chained via 'from e' so the original cause is preserved. This normalizes arbitrary user-function failures (syntax errors, type errors, network failures inside the fn) into a single prompt-domain error type. FastMCPError subclasses pass through unwrapped.

Source

Thrown at fastmcp_slim/fastmcp/prompts/function_prompt.py:363

            # self.fn is wrapped by without_injected_parameters which handles
            # dependency resolution internally
            if is_coroutine_function(self.fn):
                result = await type_adapter.validate_python(kwargs)
            else:
                # Run sync functions in threadpool to avoid blocking the event loop
                result = await call_sync_fn_in_threadpool(
                    type_adapter.validate_python, kwargs
                )
                # Handle sync wrappers that return awaitables (e.g., partial(async_fn))
                if inspect.isawaitable(result):
                    result = await result

            return self.convert_result(result)
        except FastMCPError:
            raise
        except Exception as e:
            logger.exception(f"Error rendering prompt {self.name}")
            raise PromptError(f"Error rendering prompt {self.name!r}: {e}") from e


@overload
def prompt(fn: F) -> F: ...
@overload
def prompt(
    name_or_fn: str,
    *,
    version: str | int | None = None,
    title: str | None = None,
    description: str | None = None,
    icons: list[Icon] | None = None,
    tags: set[str] | None = None,
    meta: dict[str, Any] | None = None,
    auth: AuthCheck | list[AuthCheck] | None = None,
) -> Callable[[F], F]: ...
@overload
def prompt(

View on GitHub (pinned to 1f02114297)

Solutions

  1. Read the chained original exception in the traceback (the 'caused by' section) to find the real root cause inside your prompt function
  2. Fix the bug in the prompt function itself — PromptError is only a wrapper
  3. Catch PromptError at the call site and fall back to a user-friendly message
  4. If your function intentionally raises a domain error, raise a FastMCPError subclass so it propagates unwrapped

Example fix

// before
def get_weather(city: str) -> str:
    return api.fetch(city)['temp']  # raises KeyError
// after
def get_weather(city: str) -> str:
    data = api.fetch(city)
    return data.get('temp', 'unknown')
Defensive patterns

Strategy: try-catch

Validate before calling

import inspect
sig = inspect.signature(prompt_fn)
sig.bind(**arguments)  # raises TypeError early if args mismatch

Try / catch

try:
    result = await prompt.render(arguments)
except PromptError as e:
    logger.error('prompt failed: %s (cause: %r)', e, e.__cause__)
    result = fallback_prompt_result
except FastMCPError:
    raise  # domain errors pass through unwrapped

Prevention

When it happens

Trigger: The function decorated with @prompt raises any non-FastMCP exception when invoked with the supplied arguments — e.g. TypeError from wrong argument types after string conversion, KeyError inside the function, API call failures, division by zero.

Common situations: The prompt function calls an external LLM/API that is down; argument type conversion produces an unexpected type (e.g. 'None' string) that the fn chokes on; a refactor changed the fn signature so a keyword mismatches; template rendering inside the fn raises.

Related errors


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