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
- Use a token belonging to an admin user, or a user with read policy for the entity
- Update the user's entity permissions in HA (Settings > People) to include the entity or use 'Allow all' read policy
- 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
- Use admin or correctly-scoped tokens for API clients
- Re-check entity permission lists after adding new entities
- Prefer the WebSocket API for third-party tooling
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
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- User is not active
- System generated users cannot have refresh tokens connected
- System generated users can only have system type refresh tok
- Client is required to generate a refresh token.
- Client_name is required for long-lived access token
AI-assisted analysis of home-assistant/core@58a3fdb3ea (2026-08-14).
Data as JSON: /api/errors/f970ad687c348deb.
Report an issue: GitHub.