{"record":{"id":"9ee9ecedb724d15d","repo":"pulumi/pulumi","slug":"optional-type-with-no-non-none-elements","errorCode":null,"errorMessage":"Optional type with no non-None elements","messagePattern":"Optional type with no non-None elements","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdk/python/lib/pulumi/provider/experimental/analyzer.py","lineNumber":881,"sourceCode":"        return _NoneType in get_args(typ)\n    return False\n\n\ndef is_any(typ: type) -> bool:\n    return typ is Any\n\n\ndef unwrap_optional(typ: type) -> type:\n    \"\"\"\n    Returns the first type of the Union that is not NoneType.\n    \"\"\"\n    if not is_optional(typ):\n        raise ValueError(\"Not an optional type\")\n    elements = get_args(typ)\n    for element in elements:\n        if element is not _NoneType:\n            return element\n    raise ValueError(\"Optional type with no non-None elements\")\n\n\ndef is_not_required(typ: Any) -> bool:\n    if not _NotRequiredTypes:\n        return False\n    return get_origin(typ) in _NotRequiredTypes\n\n\ndef unwrap_not_required(typ: Any) -> type:\n    if not is_not_required(typ):\n        raise ValueError(f\"{typ} is not a NotRequired type\")\n    return get_args(typ)[0]\n\n\ndef is_required(typ: Any) -> bool:\n    if not _RequiredTypes:\n        return False\n    return get_origin(typ) in _RequiredTypes","sourceCodeStart":863,"sourceCodeEnd":899,"githubUrl":"https://github.com/pulumi/pulumi/blob/793f7b2e160db4321fb7fb6b0607461e01cb251e/sdk/python/lib/pulumi/provider/experimental/analyzer.py#L863-L899","documentation":"Raised by unwrap_optional() in the Pulumi Python component analyzer. Given a typing annotation, it asserts the type is Optional (a Union containing None) and returns the single non-None element. If the annotation is optional-shaped per is_optional() but get_args() yields only NoneType elements (or no args at all), there is nothing to unwrap, so this ValueError is thrown.","triggerScenarios":"Calling unwrap_optional() (directly or via type analysis in the experimental component provider) with a type whose get_args() contains no element other than NoneType — effectively a degenerate Optional[None]/Union[None] annotation on a component input or property.","commonSituations":"Annotating a component argument as Optional[None] or Union[None] by mistake; dynamic/programmatically-built annotations where the real inner type was dropped; odd results from get_type_hints on forward refs that resolve to None; typos like Optional() without a parameter.","solutions":["Fix the annotation to include a concrete inner type, e.g. Optional[str] instead of Optional[None] or bare None","If the type is built dynamically, verify get_args(typ) before calling unwrap_optional","Check for typos where the type argument was omitted","If a property should just be optional, express it as Optional[InnerT] or NotRequired[InnerT] in the args class"],"exampleFix":"# before\nclass MyArgs(TypedDict):\n    name: Optional[None]\n\n# after\nclass MyArgs(TypedDict):\n    name: Optional[str]","handlingStrategy":"type-guard","validationCode":"from typing import get_args, get_origin, Union, Optional\nimport types\ndef check_optional_has_inner(typ):\n    if get_origin(typ) not in (Union, types.UnionType):\n        return False\n    return any(a is not type(None) for a in get_args(typ))\nassert check_optional_has_inner(MyArgs.__annotations__[\"name\"])","typeGuard":"def is_real_optional(typ) -> bool:\n    import types, typing\n    origin = get_origin(typ)\n    if origin is not Union and origin is not types.UnionType:\n        return False\n    args = get_args(typ)\n    return type(None) in args and len(args) > 1","tryCatchPattern":"try:\n    inner = unwrap_optional(typ)\nexcept ValueError:\n    inner = None  # or fix the annotation upstream","preventionTips":["Always parameterize Optional with a concrete type","Lint annotations with mypy/pyright to catch Optional[None]","Prefer NotRequired[InnerT] for TypedDict optionality"],"tags":["python","type-annotations","pulumi-components"],"backgroundTag":"invalid-type-annotation","analyzedSha":"793f7b2e160db4321fb7fb6b0607461e01cb251e","analyzedAt":"2026-08-31T09:36:43.099Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}