apache/superset · error · NotAuthorizedException

The user is not authorized to {what_not_authorized}

Error message

The user is not authorized to {what_not_authorized}

What it means

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.

Source

Thrown at superset/common/not_authorized_object.py:27

#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
from typing import Any, Optional

from superset.exceptions import SupersetException


class NotAuthorizedObject:
    def __init__(self, what_not_authorized: str):
        self._what_not_authorized = what_not_authorized

    def __getattr__(self, item: Any) -> None:
        raise NotAuthorizedException(self._what_not_authorized)

    def __getitem__(self, item: Any) -> None:
        raise NotAuthorizedException(self._what_not_authorized)


class NotAuthorizedException(SupersetException):
    def __init__(
        self, what_not_authorized: str = "", exception: Optional[Exception] = None
    ) -> None:
        super().__init__(
            "The user is not authorized to " + what_not_authorized, exception
        )

View on GitHub (pinned to f4587218dd)

Solutions

  1. Check the object type/authorization before attribute access (isinstance against the real model class).
  2. Use security_manager.can_access() in the caller to gate the code path.
  3. Fix the template/logic to render a fallback for objects the user cannot access.

Example fix

# before
name = obj.slice_name  # raises if obj is NotAuthorizedObject

# after
if isinstance(obj, NotAuthorizedObject):
    name = "(restricted)"
else:
    name = obj.slice_name
Defensive patterns

Strategy: type-guard

Validate before calling

from superset.common.not_authorized_object import NotAuthorizedObject
if isinstance(obj, NotAuthorizedObject):
    render_restricted_placeholder()

Type guard

def is_real_model(obj: Any, cls: type) -> bool:
    return isinstance(obj, cls) and not isinstance(obj, NotAuthorizedObject)

Try / catch

from superset.common.not_authorized_object import NotAuthorizedException
try:
    value = obj.attr
except NotAuthorizedException:
    value = None

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of apache/superset@f4587218dd (2026-08-14). Data as JSON: /api/errors/55eecbcb8a298ed6. Report an issue: GitHub.