Applies to:
- Plan:
- Deployment:
Summary
Issue: BTQL queries usingshape => 'summary' fail with 500 (surfaced as 502 at the GCE load balancer) with SigningError: Permission 'iam.serviceAccounts.signBlob' denied. Queries without shape => 'summary' succeed.
Cause: The shape => 'summary' code path uses @google-cloud/storage to generate V4 signed GCS URLs when result sets exceed 4 MB. This requires iam.serviceAccounts.signBlob, which is implicitly available on GKE Autopilot but must be explicitly granted on GKE Standard with Workload Identity.
Resolution: Grant roles/iam.serviceAccountTokenCreator to the Braintrust service account and apply the two related bucket IAM bindings.
Resolution steps
Step 1: Add the missing IAM bindings via Terraform
Apply three resources matching upstream PR #13:Step 2: Verify the fix
Run a query withshape => 'summary' against a large result set and confirm a 200 response:
Background
Why only large result sets fail
Results under 4 MB are returned inline — no signed URL is generated andsignBlob is never called. Results over 4 MB are materialized to GCS and returned as a signed URL, which requires iam.serviceAccounts.signBlob. This is why some shape => 'summary' queries succeed while aggregation queries on large result sets always fail.
The threshold is configurable via the RESPONSE_BUCKET_OVERFLOW_THRESHOLD environment variable on the API pod.
GKE Autopilot vs. GKE Standard
On GKE Autopilot, the default node service account has broad enough permissions to coversignBlob implicitly. On GKE Standard with Workload Identity, the pod service account only has explicitly granted roles. The roles/iam.serviceAccountTokenCreator binding must be added manually if your fork predates the upstream Terraform change.