{"record":{"id":"6aaab029f203c95a","repo":"mlflow/mlflow","slug":"cannot-revert-the-attribute-named-s-since-the-s","errorCode":null,"errorMessage":"Cannot revert the attribute named '%s' since the setting 'store_hit' was not set to True when applying the patch.","messagePattern":"Cannot revert the attribute named '(.+?)' since the setting 'store_hit' was not set to True when applying the patch\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"mlflow/utils/gorilla.py","lineNumber":359,"sourceCode":"    Notice:\n    This method is taken from\n    https://github.com/christophercrouzet/gorilla/blob/v0.4.0/gorilla.py#L318-L351\n    with modifictions for autologging disablement purposes.\n    \"\"\"\n    # If an curr_active_patch has not been set on destination class for the current patch,\n    # then the patch has not been applied and we do not need to revert anything.\n    curr_active_patch = _ACTIVE_PATCH % (patch.name,)\n    if curr_active_patch not in patch.destination.__dict__:\n        # already reverted.\n        return\n\n    original_name = _ORIGINAL_NAME % (patch.name,)\n\n    if patch.is_inplace_patch:\n        # check whether original_name is in destination. We cannot use hasattr because it will\n        # try to get attribute from parent classes if attribute not found in destination class.\n        if original_name not in patch.destination.__dict__:\n            raise RuntimeError(\n                \"Cannot revert the attribute named '%s' since the setting \"  # noqa: UP031\n                \"'store_hit' was not set to True when applying the patch.\"\n                % (patch.destination.__name__,)\n            )\n        # restore original method\n        # during reverting patch, we need restore the raw attribute to the patch point\n        # so get original attribute bypassing descriptor protocal\n        original = object.__getattribute__(patch.destination, original_name)\n        setattr(patch.destination, patch.name, original)\n    else:\n        # delete patched method\n        delattr(patch.destination, patch.name)\n\n    if original_name in patch.destination.__dict__:\n        delattr(patch.destination, original_name)\n    delattr(patch.destination, curr_active_patch)\n\n","sourceCodeStart":341,"sourceCodeEnd":377,"githubUrl":"https://github.com/mlflow/mlflow/blob/6a27f2decc0b76eb1b54af31849784addb357dbc/mlflow/utils/gorilla.py#L341-L377","documentation":"gorilla.revert() cannot restore the original attribute because the patch that overwrote it was applied with store_hit=False (or default settings), so no _original_<name> backup exists in the destination's __dict__. For in-place patches (patch.name was already in destination.__dict__ at apply time), reverting requires that stored original. MLflow raises RuntimeError rather than silently losing the pre-patch implementation.","triggerScenarios":"Calling gorilla.revert(patch) (directly or via revert_patches / patched_fit teardown) where patch.is_inplace_patch is True and the key '_original_<name>' is not in patch.destination.__dict__, i.e. the patch was applied without Settings(store_hit=True).","commonSituations":"Autologging was enabled with allow_hit=True but store_hit left False, then mlflow.autolog(disable=True) or revert_patches() runs; test teardown trying to undo a patch applied manually in setup; mixed patch versions where one process patched with store_hit and another tries to revert.","solutions":["Re-apply the patch with gorilla.Settings(allow_hit=True, store_hit=True), then revert it","Manually restore the original implementation: set patch.destination.<name> back to the original function you saved before patching","If the original is unrecoverable, delete the patched attribute and re-set it from the parent class or a fresh class definition","Avoid mixing: standardize on store_hit=True wherever allow_hit=True is used"],"exampleFix":"// before\ngorilla.apply(gorilla.Patch(Cls, 'fit', wrapper, gorilla.Settings(allow_hit=True)))\n...\ngorilla.revert(patch)  # RuntimeError: store_hit was not True\n// after\ngorilla.apply(gorilla.Patch(Cls, 'fit', wrapper, gorilla.Settings(allow_hit=True, store_hit=True)))\n...\ngorilla.revert(patch)","handlingStrategy":"try-catch","validationCode":"orig = '_original_' + patch.name\nif patch.is_inplace_patch and orig not in patch.destination.__dict__:\n    raise RuntimeError('Cannot revert: re-apply patch with store_hit=True first')","typeGuard":"def is_revertible(patch) -> bool:\n    return (not patch.is_inplace_patch) or ('_original_%s' % patch.name) in patch.destination.__dict__","tryCatchPattern":"try:\n    gorilla.revert(patch)\nexcept RuntimeError as e:\n    if 'store_hit' in str(e):\n        logger.warning('Original not stored; manually restoring %s', patch.name)\n        setattr(patch.destination, patch.name, original_impl)\n    else:\n        raise","preventionTips":["Always pair allow_hit=True with store_hit=True","Keep a reference to the original function before any manual patching","Use a context manager that applies and reverts with consistent settings"],"tags":["monkey-patching","python","gorilla","revert"],"backgroundTag":"monkey-patch-revert-without-stored-original","analyzedSha":"6a27f2decc0b76eb1b54af31849784addb357dbc","analyzedAt":"2026-08-29T20:54:51.419Z","schemaVersion":2},"datasetVersion":"2026-08-29T22:17:34.462Z"}