{"record":{"id":"3bbad8ea1fb32fb5","repo":"dbt-labs/dbt-core","slug":"role-must-be-a-string","errorCode":null,"errorMessage":"role must be a string","messagePattern":"role must be a string","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbt-adapter/src/adapter/mod.rs","lineNumber":2312,"sourceCode":"\n                let database = grant_target.project.as_deref().ok_or_else(|| {\n                    minijinja::Error::new(\n                        minijinja::ErrorKind::InvalidOperation,\n                        \"project in a GrantAccessToTarget cannot be empty\",\n                    )\n                })?;\n                let schema = grant_target.dataset.as_deref().ok_or_else(|| {\n                    minijinja::Error::new(\n                        minijinja::ErrorKind::InvalidOperation,\n                        \"dataset in a GrantAccessToTarget cannot be empty\",\n                    )\n                })?;\n\n                let role = if role_val.is_none() || role_val.is_undefined() {\n                    None\n                } else {\n                    Some(role_val.as_str().ok_or_else(|| {\n                        minijinja::Error::new(\n                            minijinja::ErrorKind::InvalidOperation,\n                            \"role must be a string\",\n                        )\n                    })?)\n                };\n\n                let entity = downcast_value_to_dyn_base_relation(entity_val)?;\n\n                let mut conn =\n                    adapter.borrow_tlocal_connection(Some(state), node_id_from_state(state))?;\n                let result = adapter.grant_access_to(\n                    state,\n                    conn.as_mut(),\n                    &entity,\n                    entity_type,\n                    role,\n                    database,\n                    schema,","sourceCodeStart":2294,"sourceCodeEnd":2330,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-adapter/src/adapter/mod.rs#L2294-L2330","documentation":"This error is raised by the `grant_access_to` adapter method when the `role` argument is provided but is not a Jinja string. The method allows `role` to be None/undefined (no role grant), but if a value is passed it must be coercible to a string via `as_str()`. dbt-core throws the equivalent Python error when `grant_access_to` receives a non-string role.","triggerScenarios":"Calling `grant_access_to(relation, privilege, role=...)` from a Jinja macro with a non-string role value, e.g. `role=none` that is not actually undefined (a literal none Value rather than undefined), a numeric, boolean, or dict/list value, or a Jinja object that does not implement string conversion.","commonSituations":"Passing a Jinja `none` literal which is neither undefined nor a string; passing an integer role ID; passing a config-derived value that resolves to a dict; typo where the caller passes a variable holding an object instead of its string name.","solutions":["Ensure the role argument is a quoted string, e.g. grant_access_to(relation, privilege, role='reporter')","If the role may be absent, omit the kwarg entirely or pass an actually-undefined variable instead of none","Convert non-string values before calling: role=my_role|string","Inspect the value with log() or print() to confirm its type before the call"],"exampleFix":"// before (Jinja)\n{{ grant_access_to(relation, 'select', role=none) }}\n// after\n{{ grant_access_to(relation, 'select', role='reporter') }}","handlingStrategy":"type-guard","validationCode":"{% if role is defined and role is not none and role is not string %}\n  {{ exceptions.raise_compiler_error(\"role must be a string, got: \" ~ role) }}\n{% endif %}","typeGuard":"{% macro is_jinja_string(v) %}\n  {{ return(v is string) }}\n{% endmacro %}","tryCatchPattern":"{% set res = adapter.dispatch('grant_access_to')(relation, privilege, role=role if role is string else none) %}","preventionTips":["Always pass role as a quoted string literal or a string-typed variable","Omit the role kwarg rather than passing none when no role is needed","Use |string filter on computed values before passing"],"tags":["jinja","adapter","type-mismatch","arguments"],"backgroundTag":"type-mismatch","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}