{"record":{"id":"6b56d3454decd15f","repo":"GoogleCloudPlatform/microservices-demo","slug":"failed-precondition","errorCode":"FAILED_PRECONDITION","errorMessage":"Unable to access cart storage due to an internal error. {ex}","messagePattern":"Unable to access cart storage due to an internal error\\. (.+?)","errorType":"error_code","errorClass":"RpcException","httpStatus":null,"severity":"critical","filePath":"src/cartservice/src/cartstore/AlloyDBCartStore.cs","lineNumber":98,"sourceCode":"            // Use INSERT ... ON CONFLICT to prevent duplicate key error\n            var insertCmd = $@\"\n                INSERT INTO {tableName} (userId, productId, quantity)\n                VALUES ('{userId}', '{productId}', {totalQuantity})\n                ON CONFLICT (userId, productId)\n                DO UPDATE SET quantity = {totalQuantity};\n            \";\n\n            await using (var cmdInsert = dataSource.CreateCommand(insertCmd))\n            {\n                await Task.Run(() =>\n                {\n                    return cmdInsert.ExecuteNonQueryAsync();\n                });\n            }\n        }\n        catch (Exception ex)\n        {   \n            throw new RpcException(\n                new Status(StatusCode.FailedPrecondition, $\"Unable to access cart storage due to an internal error. {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            cart.UserId = userId;\n            try\n            {\n                await using var dataSource = NpgsqlDataSource.Create(connectionString);\n\n                var cartFetchCmd = $\"SELECT productId, quantity FROM {tableName} WHERE userId = '{userId}'\";\n                var cmd = dataSource.CreateCommand(cartFetchCmd);\n                await using (var reader = await cmd.ExecuteReaderAsync())\n                {","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/GoogleCloudPlatform/microservices-demo/blob/72ba613a05f7fcee51cf1d0badff401b6ae7074d/src/cartservice/src/cartstore/AlloyDBCartStore.cs#L80-L116","documentation":"AlloyDBCartStore.AddItemAsync wraps every AlloyDB (Npgsql) operation in a try/catch and rethrows any exception as a gRPC RpcException with status FailedPrecondition and the message 'Unable to access cart storage due to an internal error. {ex}'. It means the cart service could not complete its SQL insert/upsert of an item into the user's cart — usually a connectivity, schema, or database availability problem, not a bad request.","triggerScenarios":"AddItemAsync(userId, item, productId, quantity) fails on its INSERT ... ON CONFLICT upsert into the carts table: connection refused/timeouts to AlloyDB, missing or uninitialized schema (table 'carts' does not exist), wrong credentials, or pool exhaustion.","commonSituations":"AlloyDB instance not provisioned or private-IP unreachable from the cart service pod; CARTSERVICE DB env vars (connection string) misconfigured; schema init script never run; VPC/network auth (IAM authdb) misconfigured after deployment changes.","solutions":["Read the inner exception text after the message in the log — it names the real Npgsql cause (connection refused, relation does not exist, auth failure)","Verify the AlloyDB connection string/env vars and that the DB host is reachable from the service (try psql or a TCP check from the same network)","Run the schema initialization (create carts table) if the error mentions relation/table not found","Restart/recycle the pod to clear a poisoned connection pool, and check AlloyDB instance health/monitoring"],"exampleFix":"// before (typical env misconfig)\nCARTSERVICE_DB_URI=alloydb://user:pass@10.0.0.1:5432/cartdb   # wrong host/private IP\n// after\nCARTSERVICE_DB_URI=alloydb://user:pass@<alloydb-instance-ip>:5432/cartdb  # reachable + schema initialized","handlingStrategy":"try-catch","validationCode":"// Before AddItemAsync, verify storage health\nvar store = new AlloyDBCartStore(connectionString);\nif (!store.Ping()) {\n    throw new InvalidOperationException(\"Cart storage (AlloyDB) is not reachable; check connection string and schema.\");\n}","typeGuard":"bool IsFailedPreconditionStorage(RpcException ex) =>\n    ex.StatusCode == StatusCode.FailedPrecondition &&\n    ex.Status.Detail.StartsWith(\"Unable to access cart storage\");","tryCatchPattern":"try {\n    await cartStore.AddItemAsync(userId, productId, quantity);\n} catch (RpcException ex) when (ex.StatusCode == StatusCode.FailedPrecondition) {\n    logger.LogError(ex, \"Cart storage write failed for user {UserId}\", userId);\n    throw new ApplicationException(\"Cart is temporarily unavailable. Please try again.\", ex);\n}","preventionTips":["Always run the schema init script (create carts table) when provisioning a new environment","Monitor the appended inner exception text — it contains the actual Npgsql error","Alert on AlloyDB instance health and connection pool saturation","Validate the DB connection string with a smoke Ping at service startup"],"tags":["grpc","alloydb","database","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"}