## TL;DR

The database role dbt connects with lacks privileges on the target schema. Grant `USAGE` and `CREATE` on the schema to that role (and future-table grants where your warehouse needs them), then rerun the model.

## Error

```text
"Database Error in model: permission denied for schema" dbt
```

## Steps

1. Identify the role dbt connects as: check the `role` or `user` in the active profiles.yml target. Expected: you know the exact role name.
2. Check what the role can do: query the warehouse for the role's grants on the target schema. Expected: you confirm USAGE or CREATE is missing.
3. Grant the missing privileges, for example on Postgres: `GRANT USAGE, CREATE ON SCHEMA analytics TO [ROLE];`. Expected: the grant succeeds.
4. On Snowflake, also grant on future tables in the schema so dbt-created tables are usable: `GRANT SELECT ON FUTURE TABLES IN SCHEMA analytics.[SCHEMA] TO [ROLE];`. Expected: future tables inherit access.
5. Rerun `dbt run --select [MODEL NAME]`. Expected: the model builds without a permission error.

## When to use

- `dbt run` fails with "permission denied for schema".
- You just added a new target schema or a new database role.

## When not to use

- The denial names a specific table (grant on the table, not the schema).
- The connection itself fails (a credentials or network problem, not a grants problem).

## Tool compatibility

- dbt Core 1.0 and later. Grant syntax is warehouse-specific; the examples above cover Postgres and Snowflake patterns.

## Variant phrasings

### permission denied for database / for relation

Sibling errors: the role lacks rights on the database or on one table; grant at the right level.

### dbt grants config not applying

If you use dbt's `grants` config, the running role must own the object or hold grant privileges itself.

## Why it happens

Warehouses deny by default. A new schema, a new role, or a rebuilt warehouse leaves dbt's role without the privileges its models need, and the first write to the schema fails.

## Edge cases

- dbt's `grants` config only works if the running role can itself grant; otherwise the config silently does nothing useful.
- On BigQuery, the equivalent is dataset-level IAM roles, not SQL grants.
- Personal dev schemas often work while shared prod schemas fail; compare the two roles' grants.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_Z2UT1K5xUm4HasFmrzAk5g
