Skip to content

Fix list projects to return NumericId and FriendlyName#431

Merged
goccy merged 1 commit into
goccy:mainfrom
aholyoke:fix/projects-list-missing-fields
Jan 24, 2026
Merged

Fix list projects to return NumericId and FriendlyName#431
goccy merged 1 commit into
goccy:mainfrom
aholyoke:fix/projects-list-missing-fields

Conversation

@aholyoke

Copy link
Copy Markdown
Contributor

Fix projects.list to return NumericId and FriendlyName

Fixes #391

Problem

The projects.list API endpoint only returns the id field for each project, but the Google Cloud BigQuery Python client expects numericId and friendlyName fields to also be present. This causes a KeyError when calling client.list_projects().

Reproduction

Start the emulator:

bigquery-emulator --project=test

Run the following Python code:

from google.api_core.client_options import ClientOptions
from google.auth.credentials import AnonymousCredentials
from google.cloud import bigquery

client_options = ClientOptions(api_endpoint="http://0.0.0.0:9050")
client = bigquery.Client(
    "test",
    client_options=client_options,
    credentials=AnonymousCredentials(),
)

for project in client.list_projects():
    print(project)

Result:

Traceback (most recent call last):
  ...
  File ".../google/cloud/bigquery/client.py", line 178, in from_api_repr
    return cls(resource["id"], resource["numericId"], resource["friendlyName"])
KeyError: 'numericId'

Fix

Add the missing NumericId and FriendlyName fields to the ProjectListProjects response:

for i, p := range projects {
    projectList = append(projectList, &bigqueryv2.ProjectListProjects{
        Id:           p.ID,
        NumericId:    uint64(i + 1),
        FriendlyName: p.ID,
    })
}
  • NumericId is assigned a sequential integer (1-indexed)
  • FriendlyName defaults to the project ID

@aholyoke

Copy link
Copy Markdown
Contributor Author

@goccy Can you review this when you have a chance?

@goccy

goccy commented Jan 24, 2026

Copy link
Copy Markdown
Owner

Thank you for your contribution ! LGTM 👍

@goccy goccy merged commit dafbca6 into goccy:main Jan 24, 2026
3 of 4 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes issue #391 by adding the missing NumericId and FriendlyName fields to the projects.list API endpoint response. The Google Cloud BigQuery Python client requires these fields to be present in the ProjectListProjects response, and their absence was causing a KeyError when calling client.list_projects().

Changes:

  • Added NumericId field (assigned as sequential 1-indexed integer based on loop position)
  • Added FriendlyName field (defaults to project ID)
  • Added test coverage for the projects.list endpoint to verify the presence of all required fields

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
server/handler.go Modified projectsListHandler.Handle to populate NumericId and FriendlyName fields in the project list response
server/server_test.go Added TestListProjects to verify the endpoint returns projects with all required fields (Id, NumericId, FriendlyName)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread server/handler.go
projectList = append(projectList, &bigqueryv2.ProjectListProjects{
Id: p.ID,
Id: p.ID,
NumericId: uint64(i + 1),

Copilot AI Jan 24, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The NumericId assignment is non-deterministic because the SQL query in FindAllProjects (line 232 of internal/metadata/repository.go) does not include an ORDER BY clause. This means the order of projects can vary between calls, causing the same project to receive different NumericIds on different invocations. Consider either: (1) adding an ORDER BY id clause to the FindAllProjects query to ensure consistent ordering, or (2) using a hash function on the project ID to generate a stable numeric ID, or (3) storing the numeric ID in the database.

Copilot uses AI. Check for mistakes.
Comment thread server/server_test.go
Comment on lines +2592 to +2602
for _, p := range projectList.Projects {
if p.Id == "" {
t.Error("Id should not be empty")
}
if p.NumericId == 0 {
t.Error("NumericId should not be zero")
}
if p.FriendlyName == "" {
t.Error("FriendlyName should not be empty")
}
}

Copilot AI Jan 24, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test should verify that NumericId assignments are stable across multiple calls to the list projects endpoint. Consider adding an assertion that calls the endpoint twice and verifies each project receives the same NumericId in both calls. This would catch the non-deterministic ordering issue.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

project.list throws KeyError

3 participants