{"record":{"id":"a0ce1fe53aeaf300","repo":"apache/superset","slug":"you-don-t-have-permission-to-modify-the-value-a0ce1f","errorCode":null,"errorMessage":"You don't have permission to modify the value.","messagePattern":"You don't have permission to modify the value\\.","errorType":"exception","errorClass":"TemporaryCacheAccessDeniedError","httpStatus":403,"severity":"error","filePath":"superset/commands/dashboard/filter_state/update.py","lineNumber":42,"sourceCode":"from superset.commands.temporary_cache.parameters import CommandParameters\nfrom superset.commands.temporary_cache.update import UpdateTemporaryCacheCommand\nfrom superset.extensions import cache_manager\nfrom superset.key_value.utils import random_key\nfrom superset.temporary_cache.utils import cache_key\nfrom superset.utils.core import get_user_id\n\n\nclass UpdateFilterStateCommand(UpdateTemporaryCacheCommand):\n    def update(self, cmd_params: CommandParameters) -> Optional[str]:\n        resource_id = cmd_params.resource_id\n        key = cmd_params.key\n        value = cast(str, cmd_params.value)  # schema ensures that value is not optional\n        check_access(resource_id)\n        entry: Entry = cache_manager.filter_state_cache.get(cache_key(resource_id, key))\n        owner = get_user_id()\n        if entry:\n            if entry[\"owner\"] != owner:\n                raise TemporaryCacheAccessDeniedError()\n\n            # Generate a new key if tab_id changes or equals 0\n            contextual_key = cache_key(\n                session.get(\"_id\"), cmd_params.tab_id, resource_id\n            )\n            key = cache_manager.filter_state_cache.get(contextual_key)\n            if not key or not cmd_params.tab_id:\n                key = random_key()\n                cache_manager.filter_state_cache.set(contextual_key, key)\n\n            new_entry: Entry = {\"owner\": owner, \"value\": value}\n            cache_manager.filter_state_cache.set(cache_key(resource_id, key), new_entry)\n        return key\n","sourceCodeStart":24,"sourceCodeEnd":56,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/dashboard/filter_state/update.py#L24-L56","documentation":"TemporaryCacheAccessDeniedError is raised by UpdateFilterStateCommand.update() when the existing cached filter-state entry's 'owner' differs from the current user id. Dashboard access already passed; this is an ownership check on the cached value, preventing one user from overwriting another user's saved filter state under the same key.","triggerScenarios":"PUT on the dashboard filter-state endpoint with a (resource_id, key) owned by another user: replaying a captured key from logs or a shared URL, or a test/automation flow that writes the initial state under a different account than the update.","commonSituations":"Integration tests where login switches between create and update steps; account switch in the same browser session retaining old keys; scripts copying filter-state keys between users to 'share' dashboard states.","solutions":["Create the filter state and update it under the same user; have the updating user issue the initial POST that generates the key.","If updating another user's state is an admin requirement, do it server-side with explicit tooling, not through the per-user cache API.","Clear stale keys on logout in the frontend so a switched account never reuses prior keys."],"exampleFix":"# before\nclient_a.post(f'/api/v1/dashboard/{rid}/filter_state/', ...)\nclient_b.put(f'/api/v1/dashboard/{rid}/filter_state/{key}', ...)  # 403\n\n# after\n# single principal owns the full lifecycle\nclient.put(f'/api/v1/dashboard/{rid}/filter_state/{key}', ...)","handlingStrategy":"try-catch","validationCode":"from superset.temporary_cache.utils import cache_key\nfrom superset.utils.core import get_user_id\n\nentry = cache_manager.filter_state_cache.get(cache_key(resource_id, key))\nif entry and entry['owner'] != get_user_id():\n    # create own state under a new key rather than updating someone else's\n    key = create_own_filter_state(resource_id)","typeGuard":null,"tryCatchPattern":"try:\n    UpdateFilterStateCommand().update(cmd_params)\nexcept TemporaryCacheAccessDeniedError:\n    # fall back to creating a new personal state entry\n    create_new_state_and_redirect()","preventionTips":["Issue the initial filter-state POST and subsequent PUTs as the same user.","Don't extract keys from logs or shared URLs for automation.","Model shared filter defaults in dashboard json_metadata, not personal cache entries."],"tags":["security","cache","filter-state","ownership","forbidden"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}