BigQuery: create() throws NullPointerException on a duplicate job id outside the US multi-region (java-bigquery#3034 not fixed by #3035)

Open Beginner friendly
#14,025 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
78/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
google-cloud, java
Domain
cloud, databases

Research direction

Start in java-bigquery/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java around lines 609–611, then compare the fixed-id branch with the nearby idRandom null handling. Review testCreateJobTryGetNotRandom and add coverage for a null re-fetch; done means a regional duplicate produces the original Already Exists error instead of a NullPointerException.

Written by the indexing model from the issue text.

Description

Environment details
  1. API: BigQuery (java-bigquery)
  2. OS type and version: macOS 15 / Linux (not OS-specific)
  3. Java version: 17
  4. Version: google-cloud-bigquery 2.68.0, and present on current main
    (java-bigquery/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java
    lines 609–611)
Summary

BigQuery.create(JobInfo) with an explicit job id throws
NullPointerException: Cannot invoke "com.google.cloud.bigquery.Job.getStatistics()" because "job" is null
when the id already exists and the job lives outside the US multi-region while the JobId carries
no location — masking the real Already Exists: Job project:location.id error.

This is the failure googleapis/java-bigquery#3034 reported. That issue was closed by
googleapis/java-bigquery#3035, which does not cover this path:

  • #3035's production change narrows the re-fetch from getJob(jobId) to
    getJob(jobId, JobOption.fields(JobField.STATISTICS)). Narrowing the requested fields cannot
    turn a null return into a job, and #3034's stack trace shows the receiver job itself was null.
  • #3035's added test (testCreateJobTryGetNotRandom) mocks the RPC getJob returning a job,
    so only the found-job path is covered; the null return has no test.

The NPE therefore still reproduces, deterministically, on 2.68.0 — which contains #3035's change.

Root cause

jobs.get resolves a JobId that names no location against the US multi-region only. When the
duplicated job's location was inferred from the statement (a query or load touching a regional
dataset), the duplicate-id handler's re-fetch misses it, getJob returns null, and
job.getStatistics() throws. The idRandom branch a few lines below already handles exactly this
case with if (job == null) { throw createException; }; the fixed-id branch lacks the same guard.

Steps to reproduce

Run the code below against any project with a dataset outside the US multi-region (reproduced
against a us-central1 dataset). No location is set anywhere; the region comes from the query.

BigQuery bq = BigQueryOptions.newBuilder().setProjectId(project).build().getService();
String sql = "SELECT COUNT(*) FROM `" + project + "." + regionalDataset + ".INFORMATION_SCHEMA.TABLES`";
String id = "npe_repro_" + System.currentTimeMillis();

bq.create(JobInfo.of(JobId.newBuilder().setProject(project).setJob(id).build(),
        QueryJobConfiguration.of(sql)));                     // ok — server infers us-central1
bq.create(JobInfo.of(JobId.newBuilder().setProject(project).setJob(id).build(),
        QueryJobConfiguration.of(sql)));                     // NullPointerException

Control arm: setting the location on the second create's JobId makes the handler find the job
and return it — the intended duplicate-id behaviour — which isolates the defect to the
location-less re-fetch.

Stack trace
java.lang.NullPointerException: Cannot invoke "com.google.cloud.bigquery.Job.getStatistics()" because "job" is null
	at com.google.cloud.bigquery.BigQueryImpl.create(BigQueryImpl.java:611)
	at com.google.cloud.bigquery.BigQueryImpl.create(BigQueryImpl.java:511)
Expected behaviour and fix

When the re-fetch returns null, fall through to the original exception, as the idRandom branch
does. Verified against BigQuery with the guard patched in: the NPE becomes
BigQueryException: Already Exists: Job flink-gcp:us-central1.npe_repro_a_…, whose message names
the job's actual location. I can send the PR.

Dominant language
Java
Stars
2.1k
Forks
1.2k
Avg merge
1d 21h
Merged PRs (30d)
131

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from googleapis/google-cloud-java

All issues in googleapis/google-cloud-java

Similar issues

More Java issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.