hasura/graphql-engine · error · ArgumentPresetExecutionError

Model permissions for model {model_name} not found for role

Error message

Model permissions for model {model_name} not found for role {role}

What it means

Thrown when the planner looks up per-role argument presets (model permissions) for a model and role combination and finds none. It means the current role has no permission/preset entry for the model being planned, so the planner cannot determine defaults or visibility for its arguments.

Source

Thrown at v3/crates/plan/src/query/arguments.rs:380

    #[error("expected {expected_type} but got a string")]
    GotString {
        expected_type: QualifiedTypeReference,
    },
    #[error("expected {expected_type} but got an object")]
    GotObject {
        expected_type: QualifiedTypeReference,
    },
    #[error("expected {expected_type} but got an array")]
    GotArray {
        expected_type: QualifiedTypeReference,
    },
    #[error(
        "could not convert the provided header value to string as it contains non-visible ASCII characters"
    )]
    IllegalCharactersInHeaderValue,
    #[error("Model source not found for model '{model_name}'")]
    ModelSourceNotFound { model_name: Qualified<ModelName> },
    #[error("Model permissions for model {model_name} not found for role {role}")]
    ModelArgumentPresetsNotFound {
        role: Role,
        model_name: Qualified<ModelName>,
    },
    #[error("command {command_name} does not have a source defined")]
    CommandSourceNotFound {
        command_name: Qualified<CommandName>,
    },
    #[error("command permissions for command {command_name} not found for role {role}")]
    CommandArgumentPresetsNotFound {
        command_name: Qualified<CommandName>,
        role: Role,
    },
    #[error("argument mapping not found for {argument_name}")]
    ArgumentMappingNotFound { argument_name: ArgumentName },
    #[error("type mapping not found for object {object_type_name}")]
    TypeMappingNotFound {
        object_type_name: Qualified<CustomTypeName>,

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Add a permissions entry for the role and model in metadata (select/filter/argument presets as appropriate)
  2. Check the exact role string sent by the client matches the role key in metadata (case-sensitive)
  3. If the role should have no access, handle this error as an authorization failure rather than a bug
  4. Reload metadata after permission changes

Example fix

// before
{"models":{"users":{"permissions":{"admin":{}}}}}
// after
{"models":{"users":{"permissions":{"admin":{},"user":{}}}}}
Defensive patterns

Strategy: validation

Validate before calling

// Check role has permissions for the model before planning
fn role_has_model_permission(metadata: &Metadata, role: &Role, model: &Qualified<ModelName>) -> bool {
    metadata.models.get(model)
        .and_then(|m| m.permissions.as_ref())
        .map(|p| p.contains_key(role)).unwrap_or(false)
}

Type guard

fn is_model_presets_not_found(e: &ArgumentPresetExecutionError) -> bool {
    matches!(e, ArgumentPresetExecutionError::ModelArgumentPresetsNotFound { .. })
}

Try / catch

match result {
    Err(PlanError::Arguments(ArgumentPresetExecutionError::ModelArgumentPresetsNotFound { role, model_name })) => {
        respond_forbidden(format!("role {role} has no permissions on {model_name}"));
    }
    other => other,
}

Prevention

When it happens

Trigger: Executing a query against a model under a role that has no permissions entry for that model — e.g. an anonymous or new role added to auth config without a matching model permission in metadata.

Common situations: Adding a new role to the auth configuration but forgetting its model permissions; restrictive role defaults after upgrading to a version that requires explicit per-role presets; typos in role names between auth headers and metadata.

Related errors


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