hasura/graphql-engine · error · ModelPermissionError

model source is required to resolve relational permissions

Error message

model source is required to resolve relational permissions

What it means

Thrown by the metadata-resolve model_permissions stage when a model declares relational permissions (insert/update/delete) but the model has no source configured. Relational permissions can only be resolved against a data-connector-backed collection, so a sourceless (e.g. command-based) model cannot carry them.

Source

Thrown at v3/crates/metadata-resolve/src/stages/model_permissions/error.rs:58

    },

    #[error(
        "a preset argument '{argument_name}' has been set for the model '{model_name}' but no such argument exists for this model"
    )]
    ModelArgumentPresetArgumentNotFound {
        model_name: Spanned<Qualified<ModelName>>,
        argument_name: Spanned<ArgumentName>,
    },

    #[error("in select filter permissions: {error}")]
    SelectFilterPermissionTypePredicateError { error: TypePredicateError },

    #[error("unknown type {custom_type_name}")]
    UnknownType {
        custom_type_name: Qualified<CustomTypeName>,
    },

    #[error("model source is required to resolve relational permissions")]
    ModelSourceRequiredForRelationalPermissions,
    #[error("unknown collection {collection} in data connector {data_connector}")]
    UnknownModelCollection {
        data_connector: Qualified<DataConnectorName>,
        collection: open_dds::data_connector::CollectionName,
    },
    #[error("relational insert is not supported for this model")]
    RelationalInsertNotSupported,
    #[error("relational update is not supported for this model")]
    RelationalUpdateNotSupported,
    #[error("relational delete is not supported for this model")]
    RelationalDeleteNotSupported,

    #[error("{0}")]
    ModelsError(#[from] models::ModelsError),
}

impl ContextualError for NamedModelPermissionError {

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Remove the insert/update/delete permission entries from the model's permissions block in the metadata
  2. Or add a valid source (data_connector + collection) to the model if relational operations are intended
  3. Re-run metadata resolve/apply after the change

Example fix

// before
models:
  MyModel:
    permissions:
      - role: admin
        insert: { ... }   # model has no source
// after
models:
  MyModel:
    permissions:
      - role: admin
        select: { ... }
Defensive patterns

Strategy: validation

Validate before calling

// before applying metadata, assert every model with relational permissions has a source
for (name, model) in models {
    let has_relational = model.permissions.iter().any(|p| p.insert.is_some() || p.update.is_some() || p.delete.is_some());
    if has_relational && model.source.is_none() {
        eprintln!("model {name} has relational permissions but no source");
    }
}

Prevention

When it happens

Trigger: Declaring SelectInsert/SelectUpdate/SelectDelete permissions under models.permissions for a model that has no 'source' (or whose source was removed), typically in the NDH metadata YAML for a model backed only by a command.

Common situations: Migrating a model from a data-connector source to a command-backed model and leaving relational permissions behind; copy-pasting a permission block from a sourced model to a sourceless one.

Related errors


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