# Access Denied: User does not have permission to query table > BigQuery sends this one message for a missing permission, a misspelled dataset, a dataset in the wrong case and a project that does not exist. Why it refuses to say which, and the order to check things in. Source: https://docs.querylab.io/bigquery-errors/access-denied-user-does-not-have-permission-to-query-table/ Updated: 2026-10-25 ```text Access Denied: Table other-project:their_dataset.events: User does not have permission to query table other-project:their_dataset.events, or perhaps it does not exist. ``` ## What to check, in order 1. Spelling and case. Dataset and table names are case-sensitive, so `SAMPLES` is not `samples`. A project id with a typo produces this error too. 2. The billing project. If you switched projects, you may have lost `bigquery.jobs.create`. 3. Whether the grant is on the table or on the dataset. A grant on one table does not cover the others. 4. Views. Reading a view requires access to its underlying tables, unless it is an [authorized view](https://docs.querylab.io/bigquery/authorized-views/). 5. Column-level security. A policy tag on a column produces a different message that names the tag. ## What BigQuery means Read the end of the sentence literally. BigQuery is saying it will not tell you which of the two it is. You get this exact text in all of these cases: - the table exists and you cannot read it - the dataset exists and you cannot read it, so the table was never looked up - the dataset name is misspelled - the dataset name has the wrong case (`SAMPLES` instead of `samples`) - the project does not exist at all That is deliberate. Confirming that `finance.salaries` exists would leak something to a person who has no access to it, so BigQuery collapses "no" and "not allowed" into one answer. The flip side is useful. If you get `Not found: Table ... was not found in location ...` instead, you have been told the table is absent, which means you can read the dataset. See [Not found: Table was not found in location](https://docs.querylab.io/bigquery-errors/not-found-table-was-not-found-in-location/) for the full decision table. Note the separator. BigQuery prints the reference as `project:dataset.table` with a colon, while you write it with a dot. ## Two separate permissions A query needs both, and the error does not say which one is missing: - `bigquery.jobs.create` on the project the query is billed to, usually from `roles/bigquery.jobUser`. This is about where the job runs, not where the data lives. - `bigquery.tables.getData` on every table and view the query references, including tables behind a view, usually from `roles/bigquery.dataViewer`. The second one is the usual cause when a query that worked for a colleague fails for you. The first one is the usual cause when a service account is involved. Running against someone else's shared dataset still needs `bigquery.jobs.create` in your own project. Ask for the roles, not the permissions. Nobody can grant you `bigquery.tables.getData` on its own. If you own the dataset, one statement does it: ```sql GRANT `roles/bigquery.dataViewer` ON SCHEMA `my-project.analytics` TO "user:someone@example.com" ``` If you do not own it, ask its owner for `roles/bigquery.dataViewer` on the dataset and your own admin for `roles/bigquery.jobUser` on your project. See [Access control](https://docs.querylab.io/bigquery/access-control/). ## Variants | Message | Cause | | ----------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | | `Access Denied: Project PROJECT_ID: User does not have bigquery.jobs.create permission in project PROJECT_ID.` | no permission to run a job in the billing project | | `Access Denied: Dataset PROJECT:DATASET: Permission bigquery.datasets.get denied on dataset PROJECT:DATASET (or it may not exist).` | a metadata read, not a query, against a dataset you cannot see | | `Access Denied: BigQuery BigQuery: User does not have permission to access data protected by policy tag` | [column-level security](https://docs.querylab.io/bigquery/column-level-security/) | | `Access denied: Requires fineGrainedGet permission on the read columns to execute the DML statements` | column-level security hit by a `DELETE`, `UPDATE` or `MERGE` | | `Access Denied: Reservation projects/.../reservations/NAME: Permission bigquery.reservations.use denied` | `SET @@reservation` without `bigquery.reservations.use` | | `IAM setPolicy failed for Dataset DATASET: Operation denied by org policy on resource.` | an organization policy, not an IAM grant | The job's `error_result.reason` for all the query cases is `accessDenied`. You can read it with `bq show -j JOB_ID` or from [`INFORMATION_SCHEMA.JOBS`](https://docs.querylab.io/bigquery/information-schema/). ## In Querylab.io Querylab.io dry-runs the query as you type, so BigQuery's message appears in the editor for free, before you run anything. See also [Projects, datasets and tables](https://docs.querylab.io/bigquery/projects-datasets-tables/). ## Sources Based on the BigQuery documentation by Google, CC BY 4.0, rewritten with examples checked against BigQuery: - [Troubleshoot query issues, User does not have permission](https://cloud.google.com/bigquery/docs/troubleshoot-queries#user_perm) - [Required permissions to run a query](https://cloud.google.com/bigquery/docs/running-queries#required_permissions) - [Grant access to a table or view](https://cloud.google.com/bigquery/docs/control-access-to-resources-iam#grant_access_to_a_table_or_view)