hasura/graphql-engine · error · PermissionError::CommandNotAccessible

no permission to select from command {command_name:}

Error message

no permission to select from command {command_name:}

What it means

PermissionError::CommandNotAccessible is raised during permission evaluation when the requesting role has no select permission (or an explicit deny) for the named command, so the query is refused before planning proceeds. It is a permissions failure, distinct from CommandNotFound which means the command doesn't exist at all.

Source

Thrown at v3/crates/plan/src/types.rs:58

            Self::Permission(permission_error) => permission_error.visibility(),
            Self::Relationship(relationship_error) => relationship_error.visibility(),
            Self::OrderBy(order_by_error) => order_by_error.visibility(),
            Self::BooleanExpression(boolean_expression_error) => {
                boolean_expression_error.visibility()
            }
            Self::Internal(_) => ErrorVisibility::Internal,
        }
    }
}

#[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>,

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Add a permission entry for the required role on the command (allow select/execute)
  2. Verify the request's session role (X-Hasura-Role) matches a role defined in the command's permissions
  3. If access should be denied, handle this error as an authorization response rather than a bug
  4. Check for typos in role names in both metadata and JWT claims

Example fix

// before
// command "get_users" has no permissions block
// after
permissions: [ { role: "user", actions: ["select"] } ]  // metadata for command get_users
Defensive patterns

Strategy: try-catch

Validate before calling

// Before executing, check the role has permission for the command
fn can_select_command(permissions: &[CommandPermission], role: &str, cmd: &str) -> bool {
    permissions.iter().any(|p| p.command == cmd && p.role == role && p.can_select)
}

Try / catch

Match PermissionError::CommandNotAccessible and convert to an HTTP 403/authorization error for the client; do not retry.

Prevention

When it happens

Trigger: Querying a command (custom query/mutation exposed by a data connector) under a role that lacks a permission entry allowing select/execute on it — e.g. as an anonymous user or a role without the command granted.

Common situations: Forgetting to add command permissions for the admin/anon/other roles; role name mismatch between the session/JWT role and metadata role definitions; testing a new command before attaching permissions; env differences where dev metadata has permissions but prod does not.

Related errors


AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28). Data as JSON: /api/errors/0f9dd235deec4cdc. Report an issue: GitHub.