Skip to content

Data Connect Emulator: Parallel gRPC queries fail with "unexpected message 'E'" in 15.4.0+ #9866

@samtsangbiz

Description

@samtsangbiz

[REQUIRED] Environment info

firebase-tools:

  • 15.5.1 - Issue present
  • 15.4.0 - Issue present
  • 15.3.1 - Works fine
  • 14.27.0 - Works fine

Platform: macOS Darwin 25.2.0 (Apple Silicon)

Node.js: v22.x

Firebase iOS SDK: 11.10.0

[REQUIRED] Test case

Firebase Configuration (firebase.json):

{
  "emulators": {
    "dataconnect": {
      "port": 9399
    }
  },
  "dataconnect": {
    "source": "dataconnect"
  }
}

Schema (dataconnect/schema/schema.gql):

type Order @table {
  id: UUID! @default(expr: "uuidV4()")
  customerId: String!
  productId: String!
  orderType: String!
  createdAt: Date!
}

type Customer @table {
  id: String! @primaryKey
  name: String!
  email: String
}

type Product @table {
  id: String! @primaryKey
  name: String!
  category: String
}

Queries (dataconnect/connector/queries.gql):

# Multiple queries executed in parallel from iOS app
query ListOrderStats90d($limit: Int = 10) @auth(level: USER_ANON) {
  orderStats90ds(orderBy: {orderCount: DESC}, limit: $limit, 
    where: {orderType: {eq: "PURCHASE"}}) {
    customer { id name }
    orderType
    orderCount
  }
}

query ListCategoryStats1d($limit: Int = 5) @auth(level: USER_ANON) {
  categoryStats1ds(orderBy: {orderCount: DESC}, limit: $limit) {
    category
    orderCount
    totalCount
    percentage
  }
}

query ListTopCustomers90d($limit: Int = 5) @auth(level: USER_ANON) {
  topCustomers90ds(orderBy: {totalSpent: DESC}, limit: $limit) {
    customer { id name }
    totalSpent
    orderCount
  }
}

# ... 5+ additional similar queries for dashboard

[REQUIRED] Steps to reproduce

  1. Install firebase-tools 15.4.0 or later (issue introduced in this version)
  2. Start emulator: firebase emulators:start
  3. Connect iOS app using Firebase Data Connect Swift SDK via gRPC
  4. Execute 5+ GraphQL queries in parallel from the iOS app (e.g., on Dashboard load)
  5. Observe that some queries fail randomly while others succeed

[REQUIRED] Expected behavior

All parallel queries should execute successfully and return data. The emulator should handle concurrent gRPC connections gracefully, similar to how production Cloud SQL handles them.

[REQUIRED] Actual behavior

When multiple gRPC queries are executed in parallel from an iOS app, the PGLite embedded database's connection pool becomes saturated, causing random query failures.

1. Connection pool warnings in Data Connect logs:

W0203 14:33:20.351079 execute.go:49 Database ping is slow 61.426209ms
stats: OpenConnections:6, InUse:6, Idle:0

2. Query failures with error (dataconnect-debug.log):

W0203 14:33:20.390336 engine.go:209 ExecuteQuery ListCategoryStats1d: failed. Connector: app
Errors: [message:"SQL execution failed" extensions:{code:INTERNAL 
  debug_details:"SQL runtime error: pq: unexpected message 'E'; expected ReadyForQuery..."}]

3. iOS Swift SDK errors (Xcode console):

11.10.0 - [FirebaseDataConnect][I-FDC000000] executeQuery(): <private> 
grpc call FAILED with {DataConnectOperationError, 
errors: Optional("SQL execution failed") 
originatingError: Optional(Swift.DecodingError.valueNotFound(Swift.Array<Any>, 
  Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "orderStats90ds", intValue: nil)], 
  debugDescription: "Cannot get unkeyed decoding container -- found null value instead", 
  underlyingError: nil)))}.

11.10.0 - [FirebaseDataConnect][I-FDC000000] executeQuery(): <private> 
grpc call FAILED with {DataConnectOperationError, 
errors: Optional("SQL execution failed") 
originatingError: Optional(Swift.DecodingError.valueNotFound(Swift.Array<Any>, 
  Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "categoryStats1ds", intValue: nil)], 
  debugDescription: "Cannot get unkeyed decoding container -- found null value instead", 
  underlyingError: nil)))}.

❌ DataConnect OrderStats Error: {DataConnectOperationError, 
errors: nil 
originatingError: Optional({DataConnectOperationError, 
errors: Optional("SQL execution failed") 
originatingError: Optional(Swift.DecodingError.valueNotFound(Swift.Array<Any>, 
  Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "orderStats90ds", intValue: nil)], 
  debugDescription: "Cannot get unkeyed decoding container -- found null value instead", 
  underlyingError: nil)))})}

❌ Dashboard: Failed to load order stats - queryFailed({DataConnectOperationError, 
errors: nil 
originatingError: Optional({DataConnectOperationError, 
errors: Optional("SQL execution failed") 
originatingError: Optional(Swift.DecodingError.valueNotFound(Swift.Array<Any>, 
  Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "orderStats90ds", intValue: nil)], 
  debugDescription: "Cannot get unkeyed decoding container -- found null value instead", 
  underlyingError: nil)))})})

Key observation: Some queries succeed (✅) while others fail (❌) in the same request batch - this is a race condition based on connection pool availability:

✅ Dashboard: Loaded 5 top customers
✅ Dashboard: Loaded 5 recent orders
❌ Dashboard: Failed to load order stats - queryFailed(...)
❌ Dashboard: Failed to load category stats - queryFailed(...)

Workaround

Downgrade to firebase-tools 15.3.1 or earlier resolves the issue completely.

npm install -g firebase-tools@15.3.1

Additional Context

  • Regression introduced in 15.4.0: Version 15.3.1 works fine, 15.4.0 and later are broken
  • HTTP requests work fine: Single queries via curl always succeed
  • Production works fine: Cloud SQL handles parallel queries without issues
  • Race condition behavior: Which queries fail depends on timing - random failures
  • Related issue: May be related to Data Connect Emulator ECONNRESET crashes from PGLite prepared statement loss #9146 (ECONNRESET crashes from PGLite)

Version Comparison

firebase-tools Status Notes
15.5.1 ❌ Broken Connection pool saturation
15.4.0 ❌ Broken Bug introduced here
15.3.1 ✅ Working Last stable version
14.27.0 ✅ Working Also stable

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions