{"record":{"id":"fb99b610d7a40c42","repo":"PrefectHQ/fastmcp","slug":"invalid-timeout-type-type-value","errorCode":null,"errorMessage":"Invalid timeout type: {type(value)}","messagePattern":"Invalid timeout type: (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/utilities/timeout.py","lineNumber":25,"sourceCode":"\ndef normalize_timeout_to_timedelta(\n    value: int | float | datetime.timedelta | None,\n) -> datetime.timedelta | None:\n    \"\"\"Normalize a timeout value to a timedelta.\n\n    Args:\n        value: Timeout value as int/float (seconds), timedelta, or None\n\n    Returns:\n        timedelta if value provided, None otherwise\n    \"\"\"\n    if value is None:\n        return None\n    if isinstance(value, datetime.timedelta):\n        return value\n    if isinstance(value, int | float):\n        return datetime.timedelta(seconds=float(value))\n    raise TypeError(f\"Invalid timeout type: {type(value)}\")\n\n\ndef normalize_timeout_to_seconds(\n    value: int | float | datetime.timedelta | None,\n) -> float | None:\n    \"\"\"Normalize a timeout value to seconds (float).\n\n    Args:\n        value: Timeout value as int/float (seconds), timedelta, or None.\n            Zero values are treated as \"disabled\" and return None.\n\n    Returns:\n        float seconds if value provided and non-zero, None otherwise\n    \"\"\"\n    if value is None:\n        return None\n    if isinstance(value, datetime.timedelta):\n        seconds = value.total_seconds()","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/utilities/timeout.py#L7-L43","documentation":"normalize_timeout_to_timedelta converts timeout settings into datetime.timedelta, accepting None, timedelta, or int/float seconds. Any other type (str, None-like objects, Decimal, etc.) raises TypeError naming the offending type. Zero/None semantics are handled; only the type is policed here.","triggerScenarios":"Passing a timeout as a string (\"30\"), Decimal, or other non-numeric type to a component/constructor that normalizes via this function (e.g. timeout=\"30\" in task configuration).","commonSituations":"Reading timeout values from environment variables or config files where they arrive as strings without conversion; JSON configs producing strings; mixing up seconds vs timedelta in typed APIs.","solutions":["Convert to a numeric type or timedelta before passing: float(value) or datetime.timedelta(seconds=...)","Parse config/env strings explicitly: timeout = float(os.environ[\"TIMEOUT\"])","Pass None for 'no timeout' rather than a string like \"none\""],"exampleFix":"// before\ncomponent = Tool(..., task_config={\"timeout\": \"30\"})\n\n// after\ncomponent = Tool(..., task_config={\"timeout\": 30})  # or datetime.timedelta(seconds=30)","handlingStrategy":"type-guard","validationCode":"def coerce_timeout(value) -> datetime.timedelta | None:\n    if value is None or isinstance(value, (datetime.timedelta, int, float)):\n        return value if not isinstance(value, str) else float(value)\n    if isinstance(value, str):\n        return float(value)\n    raise TypeError(f\"unsupported timeout: {type(value)}\")","typeGuard":"def is_valid_timeout(v) -> bool:\n    return v is None or isinstance(v, (datetime.timedelta, int, float)) and not isinstance(v, bool)","tryCatchPattern":"try:\n    comp = Tool(..., task_config={\"timeout\": raw_timeout})\nexcept TypeError as e:\n    if \"Invalid timeout type\" in str(e):\n        raw_timeout = float(raw_timeout)  # strings from env/config\n    else:\n        raise","preventionTips":["Parse env/config timeouts with float() at load time","Use typed config models (pydantic) for durations","Never pass string durations like \"30s\" to numeric timeout fields"],"tags":["python","type-error","timeout","configuration"],"backgroundTag":"invalid-timeout-type","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}