{"record":{"id":"32063a5cda082949","repo":"pulumi/pulumi","slug":"cannot-apply-input-type-and-output-type-more-tha","errorCode":null,"errorMessage":"Cannot apply @input_type and @output_type more than once.","messagePattern":"Cannot apply @input_type and @output_type more than once\\.","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"sdk/python/lib/pulumi/_types.py","lineNumber":467,"sourceCode":"def _py_properties(cls: type) -> tuple[tuple[str, str, builtins.property], ...]:\n    result: list[tuple[str, str, builtins.property]] = []\n    for base in reversed(cls.__mro__):\n        for python_name, v in base.__dict__.items():\n            if isinstance(v, builtins.property):\n                prop = v\n                pulumi_name = getattr(prop.fget, _PULUMI_NAME, MISSING)\n                if pulumi_name is not MISSING:\n                    result.append((python_name, cast(str, pulumi_name), prop))\n    return tuple(result)\n\n\ndef input_type(cls: type[T]) -> type[T]:\n    \"\"\"\n    Returns the same class as was passed in, but marked as an input type.\n    \"\"\"\n\n    if is_input_type(cls) or is_output_type(cls):\n        raise AssertionError(\n            \"Cannot apply @input_type and @output_type more than once.\"\n        )\n\n    # Get the input properties and mark the class as an input type.\n    _process_class(cls, _PULUMI_INPUT_TYPE, is_input=True, setter=True)\n\n    # Helper to create a setter function.\n    def create_setter(name: str) -> Callable:\n        def setter_fn(self, value):\n            set(self, name, value)\n\n        return setter_fn\n\n    # Now, process the class's properties, replacing properties with empty setters with\n    # an actual setter.\n    for python_name, _, prop in _py_properties(cls):  # type: ignore[arg-type] # https://github.com/python/mypy/issues/11470\n        if prop.fset is not None and _utils.is_empty_function(prop.fset):\n            setter_fn = create_setter(python_name)","sourceCodeStart":449,"sourceCodeEnd":485,"githubUrl":"https://github.com/pulumi/pulumi/blob/793f7b2e160db4321fb7fb6b0607461e01cb251e/sdk/python/lib/pulumi/_types.py#L449-L485","documentation":"The `@input_type` decorator in sdk/python/lib/pulumi/_types.py:463-468 raises AssertionError when the class is already marked as an input type or an output type. A class may be decorated as a Pulumi type at most once, since the markers drive property translation and dict conversion.","triggerScenarios":"Applying `@input_type` to a class that already has `@input_type` (e.g. stacked decorators, subclass re-decoration, or a module imported twice applying decorators), or applying `@input_type` to a class already decorated with `@output_type`.","commonSituations":"Refactoring a class from output to input type and leaving both decorators; accidentally stacking decorators during a merge; generated code that re-applies the decorator.","solutions":["Remove the duplicate decorator so the class carries only @input_type or @output_type","If it must be both input- and output-shaped, define a separate output type class or use Input/Output wrappers on plain types","Check that generated/vendor code isn't re-decorating an already-decorated class"],"exampleFix":"# before\n@input_type\n@output_type\nclass Foo:\n    ...\n# after\n@output_type\nclass Foo:\n    ...","handlingStrategy":"validation","validationCode":"import pulumi._types as pt\nif pt.is_input_type(cls) or pt.is_output_type(cls):\n    raise TypeError(f\"{cls.__name__} is already decorated as a Pulumi type\")\ncls = pulumi.input_type(cls)","typeGuard":"def can_apply_input_type(cls: type) -> bool:\n    return not (hasattr(cls, '_pulumi_input_type') or hasattr(cls, '_pulumi_output_type'))","tryCatchPattern":"try:\n    cls = pulumi.input_type(cls)\nexcept AssertionError as e:\n    if \"more than once\" in str(e):\n        pass  # already decorated; use as-is\n    else:\n        raise","preventionTips":["Keep exactly one Pulumi type decorator per class","Search your module for stacked decorators before refactoring between input and output types","Regenerate provider SDKs instead of hand-adding decorators to generated classes"],"tags":["python","assertionerror","decorators","input-types","output-types"],"backgroundTag":"duplicate-decorator","analyzedSha":"793f7b2e160db4321fb7fb6b0607461e01cb251e","analyzedAt":"2026-08-31T09:36:43.099Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}