{"record":{"id":"55eecbcb8a298ed6","repo":"apache/superset","slug":"the-user-is-not-authorized-to-what-not-authorized","errorCode":null,"errorMessage":"The user is not authorized to {what_not_authorized}","messagePattern":"The user is not authorized to (.+?)","errorType":"exception","errorClass":"NotAuthorizedException","httpStatus":500,"severity":"error","filePath":"superset/common/not_authorized_object.py","lineNumber":27,"sourceCode":"#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\nfrom typing import Any, Optional\n\nfrom superset.exceptions import SupersetException\n\n\nclass NotAuthorizedObject:\n    def __init__(self, what_not_authorized: str):\n        self._what_not_authorized = what_not_authorized\n\n    def __getattr__(self, item: Any) -> None:\n        raise NotAuthorizedException(self._what_not_authorized)\n\n    def __getitem__(self, item: Any) -> None:\n        raise NotAuthorizedException(self._what_not_authorized)\n\n\nclass NotAuthorizedException(SupersetException):\n    def __init__(\n        self, what_not_authorized: str = \"\", exception: Optional[Exception] = None\n    ) -> None:\n        super().__init__(\n            \"The user is not authorized to \" + what_not_authorized, exception\n        )\n","sourceCodeStart":9,"sourceCodeEnd":40,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/common/not_authorized_object.py#L9-L40","documentation":"NotAuthorizedObject is a decoy object whose __getattr__ raises NotAuthorizedException('The user is not authorized to ...'). Superset returns it in place of real objects (e.g. an_explore or security-manager-gated objects) so that ANY attribute access on an unauthorized surrogate fails loudly with a message naming the denied capability. This entry is the __getattr__ raise site.","triggerScenarios":"User code or templates touching an attribute of an object that Superset replaced with NotAuthorizedObject because the current principal lacks access — e.g. accessing properties on chart/datasource surrogates returned for users without the relevant permission.","commonSituations":"Jinja templates or custom code assuming every object in a collection is a real model; embedded/limited-role sessions where some objects come back as authorization placeholders; plugins enumerating fields of objects without checking type.","solutions":["Check the object type/authorization before attribute access (isinstance against the real model class).","Use security_manager.can_access() in the caller to gate the code path.","Fix the template/logic to render a fallback for objects the user cannot access."],"exampleFix":"# before\nname = obj.slice_name  # raises if obj is NotAuthorizedObject\n\n# after\nif isinstance(obj, NotAuthorizedObject):\n    name = \"(restricted)\"\nelse:\n    name = obj.slice_name","handlingStrategy":"type-guard","validationCode":"from superset.common.not_authorized_object import NotAuthorizedObject\nif isinstance(obj, NotAuthorizedObject):\n    render_restricted_placeholder()","typeGuard":"def is_real_model(obj: Any, cls: type) -> bool:\n    return isinstance(obj, cls) and not isinstance(obj, NotAuthorizedObject)","tryCatchPattern":"from superset.common.not_authorized_object import NotAuthorizedException\ntry:\n    value = obj.attr\nexcept NotAuthorizedException:\n    value = None","preventionTips":["Never assume collection members are real models","Gate with security_manager.can_access before access"],"tags":["authorization","rbac","runtime","backend"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}