```python
from google.cloud import bigquery
client = bigquery.Client(project="[PROJECT-ID]", location="EU")
job = client.query("SELECT 1")
for row in job.result():
    print(row)
```

The location trap: BigQuery datasets live in a location (US, EU, or a region). The query JOB also has a location, and it must match the dataset location. If they differ you get `Not found: Dataset [PROJECT]:[DATASET]` even though the dataset obviously exists. Agents misread this as a permissions error every time.

Fixes:
- Construct the client with location set, as above.
- Or pass job_config: `bigquery.QueryJobConfig()` does not take location; set it on the client or via `client.query(sql, location="EU")` in newer versions. Check your installed version's signature.

Other things that bite:
- `job.result()` blocks until done. For long queries use a timeout and poll, or the query can hang your script.
- Dry run first for cost control: `job_config = bigquery.QueryJobConfig(dry_run=True)` then check `job.total_bytes_processed` before running for real.
- Default project vs query project: the client project is billed for the query (needs bigquery.jobs.create there); the SQL can reference datasets in other projects you can read. Do not confuse "project that pays" with "project that holds data".
- Use parameterized queries (`query_params`) instead of f-string interpolation. SQL injection is not just a web problem.

Verify: run a trivial `SELECT 1` in the right location, then your real query as a dry run to see bytes processed.