hasura/graphql-engine · error · PermissionError::ModelNotAccessible
no permission to select from model {model_name:}
Error message
no permission to select from model {model_name:} What it means
PermissionError::ModelNotAccessible means permission evaluation found the model but the current role has no permission to select from it. The request is rejected at the permissions stage before any data source query is planned.
Source
Thrown at v3/crates/plan/src/types.rs:67
}
#[derive(Debug, thiserror::Error)]
// errors thrown during permissions evaluation, but not necessary errors due to permisssions
pub enum PermissionError {
#[error("command {command_name:} could not be found")]
CommandNotFound {
command_name: Qualified<CommandName>,
},
#[error("no permission to select from command {command_name:}")]
CommandNotAccessible {
command_name: Qualified<CommandName>,
},
#[error("model {model_name:} could not be found")]
ModelNotFound { model_name: Qualified<ModelName> },
#[error("model {model_name:} has no source")]
ModelHasNoSource { model_name: Qualified<ModelName> },
#[error("no permission to select from model {model_name:}")]
ModelNotAccessible { model_name: Qualified<ModelName> },
#[error("object type {object_type_name:} could not be found")]
ObjectTypeNotFound {
object_type_name: Qualified<CustomTypeName>,
},
#[error("no permission to select from type {object_type_name:}")]
ObjectTypeNotAccessible {
object_type_name: Qualified<CustomTypeName>,
},
#[error("no permission to select from field {field_name:} in type {object_type_name:}")]
ObjectFieldNotFound {
object_type_name: Qualified<CustomTypeName>,
field_name: FieldName,
},
#[error("Object boolean expression type {boolean_expression_type_name} could not be found")]
ObjectBooleanExpressionTypeNotFound {
boolean_expression_type_name: Qualified<CustomTypeName>,View on GitHub (pinned to 724551b9ae)
Solutions
- Grant select permission on the model for the requesting role in metadata
- Confirm the effective role from the session variables matches the role the permission is defined for
- Audit permissions with the CLI/console for the failing model
- If intentional, return a 403-style response to the client instead of treating it as an error
Example fix
// before
// model "users": no select permission for role "anon"
// after
select_permissions: [ { role: "anon", permission: { filter: {} } } ] Defensive patterns
Strategy: try-catch
Validate before calling
fn can_select_model(perms: &[ModelPermission], role: &str, model: &str) -> bool {
perms.iter().any(|p| p.model == model && p.role == role)
} Try / catch
Match PermissionError::ModelNotAccessible, return 403 with the model name; never leak it to untrusted clients if the model is hidden.
Prevention
- Grant select permissions when tracking new models
- Keep dev/prod metadata permissions in sync via versioned metadata
- Test queries under each real role, not only admin
When it happens
Trigger: Querying a model under a role with no select permission for that model — e.g. anonymous access to a table where only 'admin' has select granted, or a role whose permission entry was removed.
Common situations: New tables tracked but no permissions granted; role mismatch between JWT claims and metadata roles; environment drift where prod metadata lacks permissions present in dev; relying on admin-only defaults while testing with another role.
Related errors
- no permission to select from command {command_name:}
- no permission to select from type {object_type_name:}
- Condition {condition_hash} not found
- Expected array or null for right-hand value of contains oper
- Expected number for {side}-hand value of comparison operatio
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/eb05d9cfdbaf20e5.
Report an issue: GitHub.