{"record":{"id":"e74d2eb922275819","repo":"benbjohnson/litestream","slug":"failed-to-create-gcs-client-bucket-s-w","errorCode":null,"errorMessage":"failed to create GCS client (bucket: %s): %w","messagePattern":"failed to create GCS client \\(bucket: (.+?)\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"gs/replica_client.go","lineNumber":87,"sourceCode":"\treturn client, nil\n}\n\n// Type returns \"gs\" as the client type.\nfunc (c *ReplicaClient) Type() string {\n\treturn ReplicaClientType\n}\n\n// Init initializes the connection to GS. No-op if already initialized.\nfunc (c *ReplicaClient) Init(ctx context.Context) (err error) {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()\n\n\tif c.client != nil {\n\t\treturn nil\n\t}\n\n\tif c.client, err = storage.NewClient(ctx); err != nil {\n\t\treturn fmt.Errorf(\"failed to create GCS client (bucket: %s): %w\", c.Bucket, err)\n\t}\n\tc.bkt = c.client.Bucket(c.Bucket)\n\n\treturn nil\n}\n\n// DeleteAll deletes all LTX files.\nfunc (c *ReplicaClient) DeleteAll(ctx context.Context) error {\n\tif err := c.Init(ctx); err != nil {\n\t\treturn err\n\t}\n\n\t// Iterate over every object and delete it.\n\tinternal.OperationTotalCounterVec.WithLabelValues(ReplicaClientType, \"LIST\").Inc()\n\tfor it := c.bkt.Objects(ctx, &storage.Query{Prefix: c.Path + \"/\"}); ; {\n\t\tattrs, err := it.Next()\n\t\tif errors.Is(err, iterator.Done) {\n\t\t\tbreak","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/gs/replica_client.go#L69-L105","documentation":"The GCS replica client could not construct a Google Cloud Storage client during Init(). storage.NewClient(ctx) uses Application Default Credentials and underlying HTTP/gRPC transport; any failure (credentials, transport init, project metadata lookup) is wrapped with the configured bucket name for context. Init() is idempotent — it returns immediately if the client already exists — so this only fires on the first client creation attempt.","triggerScenarios":"Calling Init() on a gs.ReplicaClient when GOOGLE_APPLICATION_CREDENTIALS is unset/unreadable, the credentials file is invalid or expired, the metadata server is unreachable (e.g. outside GCP without explicit credentials), or the storage client transport fails to initialize.","commonSituations":"Running litestream in Docker/K8s without mounting the service-account key; GOOGLE_APPLICATION_CREDENTIALS pointing to a deleted or malformed JSON file; running locally with `gcloud auth application-default login` never executed; GCE metadata endpoint blocked by network policy.","solutions":["Set GOOGLE_APPLICATION_CREDENTIALS to a valid service-account JSON key with storage access to the bucket","If outside GCP, run `gcloud auth application-default login` or pass explicit credentials options to storage.NewClient","Verify the key file exists and is readable by the litestream process (check container mounts and file permissions)","Confirm network access to the GCS/metadata endpoints (oauth2.googleapis.com, metadata.google.internal)","Check the wrapped cause (%w) for the specific underlying failure, e.g. credential parse errors"],"exampleFix":"// before (Dockerfile) — no credentials provided\nCMD [\"litestream\", \"replicate\", \"/etc/litestream.yml\"]\n\n// after\nCOPY sa-key.json /etc/litestream/sa-key.json\nENV GOOGLE_APPLICATION_CREDENTIALS=/etc/litestream/sa-key.json\nCMD [\"litestream\", \"replicate\", \"/etc/litestream.yml\"]","handlingStrategy":"validation","validationCode":"if os.Getenv(\"GOOGLE_APPLICATION_CREDENTIALS\") == \"\" && !runningOnGCP() {\n    return fmt.Errorf(\"no GCP credentials found: set GOOGLE_APPLICATION_CREDENTIALS\")\n}","typeGuard":null,"tryCatchPattern":"if err := rc.Init(ctx); err != nil {\n    var credErr *googleapi.Error\n    if os.Getenv(\"GOOGLE_APPLICATION_CREDENTIALS\") == \"\" {\n        // fix credentials before retrying\n    }\n    return err\n}","preventionTips":["Always set GOOGLE_APPLICATION_CREDENTIALS or rely on workload identity when running in GCP","Smoke-test credentials with `gsutil ls gs://<bucket>` using the same identity before deploying","Mount service-account keys read-only and verify at container startup"],"tags":["gcs","authentication","cloud-storage","initialization"],"backgroundTag":"missing-credentials","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}