prisma: Prisma Client with MongoDB returns `ConnectorError/RawDatabaseError` "Broken pipe (os error 32)"

Bug description

It happens at random times, I couldn’t find a use case. It seems as a Rust error, but there is no problem when the request is repeated.

Invalid `this.prisma.subscription.count()` invocation in
Error occurred during query execution:
ConnectorError(ConnectorError { user_facing_error: None, kind: RawDatabaseError { code: "unknown", message: "Broken pipe (os error 32)" } })

How to reproduce

I’m not exactly sure either, I just have the error log

This error occurred in 26 of 3421 requests in the last 2 weeks

Expected behavior

No response

Prisma information

model Subscription {
  id                  String           @id @default(uuid()) @map("_id")
  subscriberAccountId String
  subscriberAccount   Account          @relation("subscribers", fields: [subscriberAccountId], references: [id])
  hostAccountId       String
  hostAccount         Account          @relation("subscriptions", fields: [hostAccountId], references: [id])
  productPriceId      String?
  productPrice        ProductPrice?    @relation("productPrice", fields: [productPriceId], references: [id])
  nextProductPriceId  String?
  nextProductPrice    ProductPrice?    @relation("productNextPrice", fields: [nextProductPriceId], references: [id])
  downgradeOption     DowngradeOption?

  paymentMethodId String?
  providerId      String?
  provider        PaymentProviders @default(stripe)
  providerStatus  String?

  currentPeriodStartAt DateTime?
  currentPeriodEndAt   DateTime?
  resubscribedAt       DateTime?

  integrations         SubscriptionIntegration
  notifications        SubscriptionNotification
  discountCode         SubscriptionDiscountCode
  payoutTransactions   PayoutTransaction[]
  subscriptionAuditLog SubscriptionAuditLog[]

  state       States    @default(ACTIVE)
  createdAt   DateTime  @default(now())
  updatedAt   DateTime? @updatedAt
  cancelAt    DateTime?
  cancelledAt DateTime?

  firebaseMeta    FirebaseMeta
  firebaseRefPath String       @unique

  @@index([hostAccountId, state])
  @@index([subscriberAccountId, state])
  @@index([hostAccountId, productPriceId, state])
  @@index([subscriberAccountId, productPriceId, state])
  @@map("subscriptions")
}
  async fetchCountBy({ hostId, subscriberId, subscriberType = SUBSCRIPTION_TABLE_FILTER_TYPES.ALL }) {
    const where = {
      AND: [{ state: SUBSCRIPTION_STATES.ACTIVE }],
    };

    if (hostId) {
      where.AND.push({ hostAccountId: hostId });
    } else {
      where.AND.push({ subscriberAccountId: subscriberId });
    }

    switch (subscriberType) {
      case SUBSCRIPTION_TABLE_FILTER_TYPES.FREE:
        where.AND.push({ productPrice: null });
        break;
      case SUBSCRIPTION_TABLE_FILTER_TYPES.PAID:
        where.AND.push({ NOT: [{ productPrice: null }] });
        break;
      case SUBSCRIPTION_PRICE_TYPES.MONTHLY:
        where.AND.push({ productPrice: { type: SUBSCRIPTION_PRICE_TYPES.MONTHLY } });
        break;
      case SUBSCRIPTION_PRICE_TYPES.ANNUAL:
        where.AND.push({ productPrice: { type: SUBSCRIPTION_PRICE_TYPES.ANNUAL } });
        break;
      case SUBSCRIPTION_PRICE_TYPES.CUSTOM:
        where.AND.push({ productPrice: { type: SUBSCRIPTION_PRICE_TYPES.CUSTOM } });
        break;
      default:
        break;
    }

    return this.prisma.subscription.count({ where });
  }

Environment & setup

  • OS: Ubuntu (Google CloudRun)
  • Database: MongoDB (Serverless)
  • Node.js version: node:16-alpine

MONGO_DATABASE_URL="mongodb+srv://<snipped>?retryWrites=true&w=majority&ssl=true"

Prisma Version

v4.5.0

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 3
  • Comments: 22 (5 by maintainers)

Most upvoted comments

@moersoy i think my suspicion was correct. We worked around this issue by retrying every mongo operation if it meets some condition. No “broken pipe” errors so far.

Probably not the cleanest code, but it solves this issue. Also this is for a remix app. You probably don’t need all the global hack stuff if you’re not using that. This is a modified version from https://github.com/prisma/prisma/issues/12814#issuecomment-1340657047

import { Prisma, PrismaClient } from "@prisma/client";
import * as retry from "retry";

let prisma: PrismaClient;

declare global {
  var __db__: PrismaClient;
}

// this is needed because in development we don't want to restart
// the server with every change, but we want to make sure we don't
// create a new connection to the DB with every change either.
// in production we'll have a single connection to the DB.
if (process.env.NODE_ENV === "production") {
  prisma = getClient();
} else {
  if (!global.__db__) {
    global.__db__ = getClient();
  }
  prisma = global.__db__;
}

function getClient() {
  const prisma = new PrismaClient();
  prisma.$connect();

  // const IGNORE_ACTIONS = ['findUnique', 'findMany', 'findFirst', 'aggregate', 'count', 'findRaw'] as const

  // DOOM retry from https://github.com/prisma/prisma/issues/12814#issuecomment-1340657047
  prisma.$use(async (params, next)=> {
    const operation = retry.operation({
      retries: 5, // 1st time is not counted
      minTimeout: 100, // 100ms
      maxTimeout: 2000, // 2 seconds
      randomize: true,
      factor: 1.97, // https://www.wolframalpha.com/input?i2d=true&i=Sum%5B100*Power%5Bx%2Ck%5D%2C%7Bk%2C0%2C4%7D%5D+%3D+3+*+1000
    })

    // HACK: run for all actions to also retry on connector errors
    // if(~IGNORE_ACTIONS.indexOf(params.action as any)) {
    //   return await next(params)
    // }

    return await new Promise((resolve, reject) => {
      operation.attempt(async (a) => {
        let result: any
        let error: any = null
        try {
          error = null
          result = await next(params)
        } catch(e) {
          // Only handle WriteConflict, "EOF" and ConnectorError issues
          // and all unknown errors
          // https://github.com/prisma/prisma/issues/16504
          if(
            (e instanceof Prisma.PrismaClientKnownRequestError && (e.code === 'P2034' || e.code === 'P2010')) ||
            (e instanceof Error && e?.message?.includes('Broken pipe')) ||
            e instanceof Prisma.PrismaClientUnknownRequestError
          ) {
            error = e
          } else {
            // This is another kind of errors, we stop retrying and reject the promise
            operation.stop()
            reject(e)
          }
        }

        // If error is null, this will be false and we can continue the execution
        if(operation.retry(error)) {
          return
        }

        if(error) {
          reject(operation.mainError())
        } else {
          resolve(result)
        }

      })
    })
  })

  return prisma;
}

export default prisma;

Getting the same issue even after upgrading Prisma to the latest version. Any workarounds? It only happens when our batch starts to run in the morning and fails once before starting to work again?

I experience this error at least once a day. It occurs on my serverless Mongodb instance occasionally after periods of no database activity for my running applications/services. I have no MongoDB connection string options enabled, such as retryable reads/writes, but the error usually seems to occur on writes. The prisma version is 4.15.0. The service is a TS-express microservice, scheduled once every 5 minutes, running 24/7.

Error logs (Mainly for occurrence periods, irrelevant data removed):

{"level":50,"time":"2023-07-15T10:40:11.804Z","pid":19116,"hostname":"colosseum","error":{"code":"P2010","clientVersion":"4.15.0","meta":{"code":"unknown","message":"Broken pipe (os error 32)"}}}
{"level":50,"time":"2023-07-15T18:10:10.880Z","pid":19116,"hostname":"colosseum","error":{"code":"P2010","clientVersion":"4.15.0","meta":{"code":"unknown","message":"Broken pipe (os error 32)"}}}
{"level":50,"time":"2023-07-15T21:10:12.114Z","pid":19116,"hostname":"colosseum","error":{"code":"P2010","clientVersion":"4.15.0","meta":{"code":"unknown","message":"Broken pipe (os error 32)"}}}
{"level":50,"time":"2023-07-15T23:40:05.648Z","pid":19116,"hostname":"colosseum","error":{"code":"P2010","clientVersion":"4.15.0","meta":{"code":"unknown","message":"Broken pipe (os error 32)"}}}
{"level":50,"time":"2023-07-15T23:40:06.268Z","pid":19116,"hostname":"colosseum","error":{"code":"P2010","clientVersion":"4.15.0","meta":{"code":"unknown","message":"Broken pipe (os error 32)"}}}
{"level":50,"time":"2023-07-16T04:00:10.137Z","pid":19116,"hostname":"colosseum","error":{"code":"P2010","clientVersion":"4.15.0","meta":{"code":"unknown","message":"Broken pipe (os error 32)"}}}
{"level":50,"time":"2023-07-16T09:45:12.859Z","pid":19116,"hostname":"colosseum","error":{"code":"P2010","clientVersion":"4.15.0","meta":{"code":"unknown","message":"Broken pipe (os error 32)"}}}
{"level":50,"time":"2023-07-16T09:45:12.860Z","pid":19116,"hostname":"colosseum","error":{"code":"P2010","clientVersion":"4.15.0","meta":{"code":"unknown","message":"Broken pipe (os error 32)"}}}
{"level":50,"time":"2023-07-16T09:50:12.199Z","pid":19116,"hostname":"colosseum","error":{"code":"P2010","clientVersion":"4.15.0","meta":{"code":"unknown","message":"Broken pipe (os error 32)"}}}
{"level":50,"time":"2023-07-16T12:00:10.190Z","pid":19116,"hostname":"colosseum","error":{"code":"P2010","clientVersion":"4.15.0","meta":{"code":"unknown","message":"Broken pipe (os error 32)"}}}
{"level":50,"time":"2023-07-16T12:00:10.191Z","pid":19116,"hostname":"colosseum","error":{"code":"P2010","clientVersion":"4.15.0","meta":{"code":"unknown","message":"Broken pipe (os error 32)"}}}
{"level":50,"time":"2023-07-16T12:05:13.527Z","pid":19116,"hostname":"colosseum","error":{"code":"P2010","clientVersion":"4.15.0","meta":{"code":"unknown","message":"Broken pipe (os error 32)"}}}

Hi @Jolg42 !

  • MongoDB Info: Version: 7.1.1 / Atlas (AWS / N. Virginia (us-east-1) / SERVERLESS. Emphasizing the use of Serverless, as I have another non-serverless instance with same app that doesn’t encounter this issue.

  • Do you see any relevant logs from your MongoDB server? No relevant logs are observed.

  • Prisma Client query that triggers this: It seems to occur with every type of query, at least with “find” queries.

  • Context in which this happens, for example, after inactivity or when doing large queries: It only occurs after a period of inactivity, specifically with the first query. Subsequent queries do not fail anymore.

  • How many documents are in your collection: Whether it’s a collection with 10 documents or 10,000, the issue persists regardless of the collection size.

Looking for something minimal to reproduce it…

@moersoy @fiws @markwoodward23 @bhjelstrom @Swertin @AlejandroDaneri @tastafur @BONDbATIF

Could you let us know:

  • what’s the version of your MongoDB server?

  • Are you using a docker image? Or a Cloud server? (please precise where it’s hosted)

  • Do you see any relevant logs from your MongoDB server?

  • the Prisma Client query that triggers this

  • in which context this happens, for example after inactivity or when doing large queries

  • how many documents are in your collection

    • Example from MongoDB Compass (the same exists in MongoDB Atlas) Screenshot 2023-12-14 at 13 25 49
  • the best, would be to have a minimal reproduction repository for us to run

Thanks!

We also encounter same issue . Raw query failed . Code Unknown . Message: Broken pipe (os error 32)

code : P2010,
clientVersion:'4.15.0',
meta:{Code `Unknown `. Message: `Broken pipe (os error 32)}

Just experienced this after inactivity

        "@prisma/client": "^5.4.2",
        "next": "13.4.11",

Cheers @Jolg42 - I’m on 4.5.0 so I’ll update and see if that changes.

Hello @eviefp, yeap. I updated the Issue