{"record":{"id":"66fe2d8ea2a9cf14","repo":"mlflow/mlflow","slug":"patching-async-property-methods-is-not-supported","errorCode":null,"errorMessage":"Patching async property methods is not supported.","messagePattern":"Patching async property methods is not supported\\.","errorType":"exception","errorClass":"MlflowException","httpStatus":null,"severity":"error","filePath":"mlflow/utils/autologging_utils/safety.py","lineNumber":292,"sourceCode":"        tags = _resolve_extra_tags(autologging_integration, extra_tags)\n        patch_function = with_managed_run(\n            autologging_integration,\n            patch_function,\n            tags=tags,\n        )\n\n    original_fn = gorilla.get_original_attribute(\n        destination, function_name, bypass_descriptor_protocol=False\n    )\n    # Retrieve raw attribute while bypassing the descriptor protocol\n    raw_original_obj = gorilla.get_original_attribute(\n        destination, function_name, bypass_descriptor_protocol=True\n    )\n    if original_fn != raw_original_obj:\n        raise RuntimeError(f\"Unsupported patch on {destination}.{function_name}\")\n    elif isinstance(original_fn, property):\n        if is_async_function:\n            raise MlflowException(\"Patching async property methods is not supported.\")\n\n        is_property_method = True\n\n        # For property decorated methods (a kind of method delegation), e.g.\n        # class A:\n        #   @property\n        #   def f1(self):\n        #     ...\n        #     return delegated_f1\n        #\n        # suppose `a1` is an instance of class `A`,\n        # `A.f1.fget` will get the original `def f1(self)` method,\n        # and `A.f1.fget(a1)` will be equivalent to `a1.f1()` and\n        # its return value will be the `delegated_f1` function.\n        # So using the `property.fget` we can construct the (delegated) \"original_fn\"\n        def original(self, *args, **kwargs):\n            # the `original_fn.fget` will get the original method decorated by `property`\n            # the `original_fn.fget(self)` will get the delegated function returned by the","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/mlflow/mlflow/blob/6a27f2decc0b76eb1b54af31849784addb357dbc/mlflow/utils/autologging_utils/safety.py#L274-L310","documentation":"`safe_patch` supports patching `@property`-decorated methods, but only synchronous ones. When the property getter is an async coroutine function, MLflow raises this because there is no supported way to wrap an async property getter safely for autologging.","triggerScenarios":"Calling `safe_patch` (directly or via an integration's `autolog()`) on a class attribute defined with `@property` whose getter is `async def` (e.g. `@property async def client(...)` in a framework class).","commonSituations":"Newer async LLM SDK versions converting a lazy sync client property into an async one; writing a custom autolog integration that targets async lazy-initializer properties.","solutions":["Patch the method that returns/awaits the property value instead of the property itself","Patch a different synchronous attribute or an internal sync method of the class","Skip autologging that specific attribute (remove it from the patch list)"],"exampleFix":"// before\nsafe_patch(FLAVOR, AsyncClient, 'session', _patch_session_fn)  # @property async def session\n// after\nsafe_patch(FLAVOR, AsyncClient, 'ensure_session', _patch_fn)  # patch the async method, not the property","handlingStrategy":"validation","validationCode":"def patch_target_is_supported(cls, name):\n    attr = inspect.getattr_static(cls, name)\n    if isinstance(attr, property) and inspect.iscoroutinefunction(attr.fget):\n        return False\n    return True","typeGuard":"def is_sync_property(attr) -> bool:\n    return isinstance(attr, property) and not inspect.iscoroutinefunction(attr.fget)","tryCatchPattern":null,"preventionTips":["Inspect class attributes with `inspect.getattr_static` before building the patch list","Exclude async properties from autolog patch lists","Patch the async method or its caller rather than the property"],"tags":["autologging","async","properties","python"],"backgroundTag":"autolog-async-property-patch","analyzedSha":"6a27f2decc0b76eb1b54af31849784addb357dbc","analyzedAt":"2026-08-29T20:54:51.419Z","schemaVersion":2},"datasetVersion":"2026-08-29T22:17:34.462Z"}