PrefectHQ/fastmcp · error · ValueError

Elicitation expected an empty response, but received: {conte

Error message

Elicitation expected an empty response, but received: {content}

What it means

When response_type resolves to None for the accept handler (an elicitation configured with no expected data), the response content must be empty. FastMCP raises this error if the client sent back any content, since there is nowhere valid to put it. This form is deprecated — elicit() now requires a response_type.

Source

Thrown at fastmcp_slim/fastmcp/server/elicitation.py:338

        AcceptedElicitation with the extracted/validated data
    """
    # For raw schemas (dict/nested-list syntax), extract value directly
    if config.is_raw:
        if not isinstance(content, dict) or "value" not in content:
            raise ValueError("Elicitation response missing required 'value' field.")
        return AcceptedElicitation[Any](data=content["value"])

    # For typed schemas, validate with Pydantic
    if config.response_type is not None:
        type_adapter = get_cached_typeadapter(config.response_type)
        validated_data = type_adapter.validate_python(content)
        if isinstance(validated_data, ScalarElicitationType):
            return AcceptedElicitation[Any](data=validated_data.value)
        return AcceptedElicitation[Any](data=validated_data)

    # For None response_type, expect empty response
    if content:
        raise ValueError(
            f"Elicitation expected an empty response, but received: {content}"
        )
    return AcceptedElicitation[dict[str, Any]](data={})


def _dict_to_enum_schema(
    enum_dict: dict[str, dict[str, str]], multi_select: bool = False
) -> dict[str, Any]:
    """Convert dict enum to SEP-1330 compliant schema pattern.

    Args:
        enum_dict: {"low": {"title": "Low Priority"}, "medium": {"title": "Medium Priority"}}
        multi_select: If True, use anyOf pattern; if False, use oneOf pattern

    Returns:
        {"type": "string", "oneOf": [...]} for single-select
        {"anyOf": [...]} for multi-select (used as array items)
    """

View on GitHub (pinned to 1f02114297)

Solutions

  1. Pass an explicit response_type (e.g. bool for a confirmation) to ctx.elicit() — response_type=None is deprecated/removed in FastMCP 4.0
  2. Update the client so it returns empty content {} for empty-schema elicitations
  3. Clear stale client state or restart the client so it re-fetches the current elicitation schema

Example fix

// before
await ctx.elicit()  # response_type=None
// after
await ctx.elicit(response_type=bool)
Defensive patterns

Strategy: try-catch

Validate before calling

# Before eliciting, ensure a response_type is supplied
if response_type is None:
    raise TypeError("ctx.elicit() requires a response_type (e.g. bool)")

Type guard

def expects_empty_response(config) -> bool:
    return config.response_type is None

Try / catch

try:
    accepted = await ctx.elicit(response_type=bool)
except ValueError as e:
    if "expected an empty response" in str(e):
        logger.warning("stale client sent data for an empty elicitation; ignoring")
        return None
    raise

Prevention

When it happens

Trigger: Calling handle_elicit_accept with a config whose response_type is None and a non-empty content dict; historically from ctx.elicit() called without a response_type whose client still submitted data.

Common situations: Legacy code using the removed response_type=None form; a client submitting form data for an elicitation that declared an empty schema; stale clients cached from before a server changed its elicitation type.

Related errors


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