home-assistant/core · error · Unauthorized

Unauthorized

Error message

Unauthorized

What it means

Unauthorized (HTTP 401) raised by GET /api/states/{entity_id} when the authenticated user lacks read permission for that specific entity. The API supports non-admin users with per-entity permission policies; the check user.permissions.check_entity(entity_id, POLICY_READ) fails, so the request never reaches the state lookup.

Source

Thrown at homeassistant/components/api/__init__.py:249

        )
        if len(body) > MIN_COMPRESSED_RESPONSE_SIZE:
            response.enable_compression()
        return response


class APIEntityStateView(HomeAssistantView):
    """View to handle EntityState requests."""

    url = "/api/states/{entity_id}"
    name = "api:entity-state"

    @ha.callback
    def get(self, request: web.Request, entity_id: str) -> web.Response:
        """Retrieve state of entity."""
        user: User = request[KEY_HASS_USER]
        hass = request.app[KEY_HASS]
        if not user.permissions.check_entity(entity_id, POLICY_READ):
            raise Unauthorized(entity_id=entity_id)

        if state := hass.states.get(entity_id):
            return web.Response(
                body=state.as_dict_json,
                content_type=CONTENT_TYPE_JSON,
            )
        return self.json_message("Entity not found.", HTTPStatus.NOT_FOUND)

    async def post(self, request: web.Request, entity_id: str) -> web.Response:
        """Update state of entity."""
        user: User = request[KEY_HASS_USER]
        if not user.is_admin:
            raise Unauthorized(entity_id=entity_id)
        hass = request.app[KEY_HASS]

        body = await request.text()

        try:

View on GitHub (pinned to 58a3fdb3ea)

Solutions

  1. Use a token belonging to an admin user, or a user with read policy for the entity
  2. Update the user's entity permissions in HA (Settings > People) to include the entity or use 'Allow all' read policy
  3. Prefer the WebSocket API with proper permission scoping for third-party integrations
Defensive patterns

Strategy: validation

Validate before calling

# Before first use, verify the token's user and permissions via the WebSocket API
# await ws.send_json({"id": 1, "type": "auth/current_user"}) and inspect permissions

Try / catch

try:
    resp = session.get(url, headers={"Authorization": f"Bearer {token}"}, timeout=5)
    if resp.status_code == 401:
        # token lacks read permission for the entity: fix user policy or use admin token
        ...

Prevention

When it happens

Trigger: Calling GET /api/states/light.kitchen with a token whose user is not admin and whose entity permissions do not include read (or an explicit deny) for light.kitchen; typical with long-lived access tokens created for restricted users, or with a user whose permissions were edited after the token was issued.

Common situations: Restricted HA user used by external tooling (Grafana, scripts, custom apps) with entity permission lists that omit newly created entities; permission policy set to entity-list instead of all; token created before permissions were narrowed.

Understand the failure class

Related errors


AI-assisted analysis of home-assistant/core@58a3fdb3ea (2026-08-14). Data as JSON: /api/errors/f970ad687c348deb. Report an issue: GitHub.