{"record":{"id":"bae9871f2b1fb6e0","repo":"GoogleCloudPlatform/microservices-demo","slug":"failed-precondition-bae987","errorCode":"FAILED_PRECONDITION","errorMessage":"Can't access cart storage at {databaseString}. {ex}","messagePattern":"Can't access cart storage at (.+?)\\. (.+?)","errorType":"error_code","errorClass":"RpcException","httpStatus":null,"severity":"critical","filePath":"src/cartservice/src/cartstore/SpannerCartStore.cs","lineNumber":99,"sourceCode":"                        new SpannerParameterCollection\n                        {\n                            { \"userId\", SpannerDbType.String },\n                            { \"productId\", SpannerDbType.String },\n                            { \"quantity\", SpannerDbType.Int64 }\n                        });\n                    cmd.Parameters[\"userId\"].Value = userId;\n                    cmd.Parameters[\"productId\"].Value = productId;\n                    cmd.Parameters[\"quantity\"].Value = currentQuantity + quantity;\n                    cmd.Transaction = transaction;\n                    await Task.Run(() =>\n                    {\n                        return cmd.ExecuteNonQueryAsync();\n                    });\n                });\n            }\n            catch (Exception ex)\n            {\n                throw new RpcException(\n                    new Status(StatusCode.FailedPrecondition, $\"Can't access cart storage at {databaseString}. {ex}\"));\n            }\n        }\n\n\n        public async Task<Hipstershop.Cart> GetCartAsync(string userId)\n        {\n            Console.WriteLine($\"GetCartAsync called for userId={userId}\");\n            Hipstershop.Cart cart = new();\n            try\n            {\n                using SpannerConnection spannerConnection = new(databaseString);\n                var cmd = spannerConnection.CreateSelectCommand(\n                    $\"SELECT * FROM {TableName} WHERE userId = @userId\",\n                    new SpannerParameterCollection {\n                        { \"userId\", SpannerDbType.String }\n                    }\n                );","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/GoogleCloudPlatform/microservices-demo/blob/72ba613a05f7fcee51cf1d0badff401b6ae7074d/src/cartservice/src/cartstore/SpannerCartStore.cs#L81-L117","documentation":"SpannerCartStore.AddItemAsync wraps its Spanner read/write transaction (upserting cart items) in a try/catch that rethrows any SpannerException as an RpcException with StatusCode.FailedPrecondition and message 'Can't access cart storage at {databaseString}. {ex}'. The message includes the Spanner database string, indicating the cart item could not be persisted to Cloud Spanner.","triggerScenarios":"AddItemAsync fails inside its session/transaction on Spanner: SPANNER_PROJECT/SPANNER_INSTANCE/SPANNER_DATABASE env vars wrong, database or table missing, IAM permission denied, or transient Spanner unavailability/timeouts.","commonSituations":"Spanner instance not provisioned or schema (carts table) never created in a new environment; service account lacking spanserver.data/database roles; env vars pointing to a deleted or different project; regional endpoint/egress issues.","solutions":["Check the inner SpannerException for the precise cause (NotFound for missing DB/table, PermissionDenied for IAM, DeadlineExceeded)","Verify SPANNER_PROJECT, SPANNER_INSTANCE, and SPANNER_DATABASE env vars match an existing database","Confirm the carts table schema was applied and the service account has the required Spanner IAM roles","Check Google Cloud Spanner monitoring for incidents and retry once transient unavailability clears"],"exampleFix":"// before\nSPANNER_PROJECT=wrong-proj SPANNER_INSTANCE=nonexistent SPANNER_DATABASE=nodb\n// after\nSPANNER_PROJECT=my-project SPANNER_INSTANCE=cart-instance SPANNER_DATABASE=cart-db  # table 'carts' initialized","handlingStrategy":"validation","validationCode":"// Validate Spanner configuration before cart operations\nvar project = Environment.GetEnvironmentVariable(\"SPANNER_PROJECT\");\nvar instance = Environment.GetEnvironmentVariable(\"SPANNER_INSTANCE\");\nvar database = Environment.GetEnvironmentVariable(\"SPANNER_DATABASE\");\nif (string.IsNullOrEmpty(project) || string.IsNullOrEmpty(instance) || string.IsNullOrEmpty(database)) {\n    throw new InvalidOperationException(\"SPANNER_PROJECT/INSTANCE/DATABASE must be set and point to an initialized carts database.\");\n}\nif (!cartStore.Ping()) {\n    throw new InvalidOperationException(\"Cannot reach Spanner database; check IAM roles and schema.\");\n}","typeGuard":"bool IsSpannerCartFailure(RpcException ex) =>\n    ex.StatusCode == StatusCode.FailedPrecondition &&\n    ex.Status.Detail.StartsWith(\"Can't access cart storage at\");","tryCatchPattern":"try {\n    await cartStore.AddItemAsync(userId, productId, quantity);\n} catch (RpcException ex) when (IsSpannerCartFailure(ex)) {\n    logger.LogError(ex, \"Spanner cart write failed for {UserId}\", userId);\n    throw new ApplicationException(\"Cart storage is temporarily unavailable; please retry.\", ex);\n}","preventionTips":["Provision the Spanner instance and apply the carts table schema before first deploy","Grant the service account spanserver.data (or equivalent Spanner database) IAM roles","Keep SPANNER_PROJECT/SPANNER_INSTANCE/SPANNER_DATABASE in a checked deployment checklist","Retry with backoff on DeadlineExceeded; alert on SpannerException rates in logs"],"tags":["grpc","spanner","gcp","cartservice","dotnet"],"backgroundTag":"cart-storage-unavailable","analyzedSha":"72ba613a05f7fcee51cf1d0badff401b6ae7074d","analyzedAt":"2026-09-02T01:15:09.673Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}