Skip to content

java.lang.NullPointerException: Cannot invoke "com.google.cloud.bigquery.TableId.getProject()" because "tableId" is null #427

@pavelfomin

Description

@pavelfomin

What happened?

The following code

        QueryJobConfiguration queryJobConfiguration = QueryJobConfiguration
            .newBuilder("SELECT * FROM dataset.table")
            .build()

        JobId jobId = JobId.newBuilder().setProject(project).setRandomJob().build()
        Job job = bigQuery.create(JobInfo.newBuilder(queryJobConfiguration)
            .setJobId(jobId)
            .build())

        TableResult tableResult = job.getQueryResults()

fails with

Cannot invoke "com.google.cloud.bigquery.TableId.getProject()" because "tableId" is null
java.lang.NullPointerException: Cannot invoke "com.google.cloud.bigquery.TableId.getProject()" because "tableId" is null
	at com.google.cloud.bigquery.BigQueryImpl.listTableData(BigQueryImpl.java:1704)
	at com.google.cloud.bigquery.BigQueryImpl.listTableData(BigQueryImpl.java:1671)
	at com.google.cloud.bigquery.Job.getQueryResults(Job.java:429)

See https://github.com/pavelfomin/spring-boot-bq-example/blob/main/src/test/groovy/com/droidablebee/springboot/bq/service/BigQueryServiceISpec.groovy. The first scenario fails when destinationTable is not set (works with real BigQuery). The second scenario sets the destinationTable explicitly as a workaround.

What did you expect to happen?

In real BigQuery:

When I run a query, BigQuery creates a temporary destination table to store the results.
Job.getQueryResults() fetches rows from this temporary table, regardless of the original table schema.
It also sets QueryJobConfiguration.destinationTable with the reference to that temporary table.

Why it works:

BigQuery dynamically creates the destination table schema based on the query output, not the source table.
The client library fetches results from this destination table, which matches the query output.

Why the emulator fails:

The emulator does not fully implement this behavior. It may not create a destination table with the correct schema, or may not set the destinationTable field in the job metadata.
The Java client expects this metadata to be present and correct, so it can fetch results from the temporary table.
If the schema doesn’t match, or the destination table is missing, you get errors (like NullPointerException).

How can we reproduce it (as minimally and precisely as possible)?

git clone [email protected]:pavelfomin/spring-boot-bq-example.git
./gradlew clean build

Anything else we need to know?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions