Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PANIC: called Result::unwrap() on an Err value: Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" } in /root/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/blocking/pool.rs:247:14 #13585

Closed
russellpekala opened this issue May 31, 2022 · 3 comments
Labels
bug/2-confirmed Bug has been reproduced and confirmed. kind/bug A reported bug. team/client Issue for team Client. tech/engines Issue for tech Engines. topic: Failed to convert rust String into napi topic: postgresql

Comments

@russellpekala
Copy link

Hi Prisma Team! My Prisma Client just crashed. This is the report:

Versions

Name Version
Node v16.4.2
OS debian-openssl-1.1.x
Prisma Client 3.14.0
Query Engine 0.1.0
Database postgresql

Logs

ng request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:libraryEngine sending request, this.libraryStarted: true
prisma:client:request_handler Error: called `Result::unwrap()` on an `Err` value: Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }
    at prismaGraphQLToJSError (/main/support/prisma/runtime/index.js:39469:10)
    at Object.request (/main/support/prisma/runtime/index.js:41333:17)
prisma:client:libraryEngine sending request, this.libraryStarted: true

Client Snippet

// PLEASE FILL YOUR CODE SNIPPET HERE

Schema

generator client {
  provider        = "prisma-client-js"
  output          = "../../../support/prisma"
  binaryTargets   = ["linux-musl", "native"]
  // see https://www.prisma.io/docs/concepts/components/prisma-schema/indexes
  previewFeatures = ["extendedIndexes"]
}

datasource db {
  provider = "postgresql"
  // automatically looks at the root folder's .env file. Nice
  url      = env("DATABASE_URL")
}

model User {
  id                        String         @id @default(uuid())
  username                  String         @unique
  displayName               String?
  email                     String         @unique
  emailVerified             Boolean        @default(false)
  createdAt                 DateTime       @default(now())
  updatedAt                 DateTime       @updatedAt
  avatarUrl                 String?
  passwordHash              String?
  followers                 User[]         @relation("UserFollowers", references: [id])
  following                 User[]         @relation("UserFollowers", references: [id])
  bio                       String?        @db.VarChar(255)
  badges                    String         @default("[]")
  Activities                Activity[]
  ActivityRefs              Activity[]     @relation(name: "FollowActivity") // activities that reference this user (not by this user).  e.g. other user followed X
  sentInvites               Invite[]       @relation("UserInvites")
  inviteId                  String         @unique
  invite                    Invite         @relation("InviteConversions", references: [id], fields: [inviteId])
  pages                     Page[]
  confirmCode               String?
  // when notifications were last cleared
  notificationsClearedAt    DateTime?
  feedClearedAt             DateTime?
  settings                  Json?
  ownedPermissions          Permission[]
  editPermissions           Permission[]   @relation("UserPermissions", references: [id])
  Block                     Block[]
  remainingInvites          Int            @default(0)
  isGoodFollow              Boolean        @default(true)
  likedBlocksAndPages       LikesOnUsers[]
  views                     View[] // what pages user has loaded
  // signup steps
  completedAvatarOnboarding Boolean        @default(false)
  completedBioOnboarding    Boolean        @default(false)
  completedBlocksOnboarding Boolean        @default(false)
  completedPagesOnboarding  Boolean        @default(false)
  completedFollowOnboarding Boolean        @default(false)
}

model Invite {
  id          String   @id @default(uuid())
  // TODO: invited by should be required but breaks seed
  invitedById String?
  invitedBy   User?    @relation("UserInvites", references: [id], fields: [invitedById])
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
  User        User?    @relation("InviteConversions")
  mnemonic    String   @unique
  expiration  DateTime @default(now())
  // used only for new, mnemonic invites. will be false for old, email based invites
  // which is fine because we won't check codes for email invites
  claimed     Boolean  @default(false)
}

enum BlockType {
  text
  image
  color
  linkEmbed
  spotifyEmbed
  youtubeEmbed
  twitterEmbed
  instagramEmbed
  file
  // Below will likely be rendered in window view
  // these are separate block types for validation purposes (e.g. type => must have embedded"X"Id)
  blockWindow
  pageWindow
  code
}

enum ImageFit {
  cover
  contain
}

enum TextSubtype {
  quote
  monospace
  plain
  headerOne
  headerTwo
  headerThree
}

model Block {
  id               String         @id @default(uuid())
  createdAt        DateTime       @default(now())
  updatedAt        DateTime       @updatedAt
  type             BlockType
  content          Json?
  isSoftDeleted    Boolean        @default(false)
  top              Int
  left             Int
  width            Int
  height           Int
  pageId           String
  page             Page           @relation(fields: [pageId], references: [id], onDelete: Cascade)
  // For embedding a block within a block
  embeddedBlockId  String?
  embeddedBlock    Block?         @relation("BlockToBlock", fields: [embeddedBlockId], references: [id])
  BlockEmbeddings  Block[]        @relation("BlockToBlock") // needed b/c self reference
  // For embedding a page within a block
  embeddedPageId   String?
  embeddedPage     Page?          @relation("EmbeddedPage", fields: [embeddedPageId], references: [id])
  Activity         Activity[]
  // The user who created the block
  user             User           @relation(fields: [userId], references: [id], onDelete: Cascade)
  userId           String
  likedBy          LikesOnUsers[]
  // content
  caption          String?
  rawContent       Json?
  description      String?
  plainText        String?
  filename         String?
  originalFilename String?
  fileSize         Int?
  hex              String?
  codeLanguage     String?
  imageFit         ImageFit?
  hasUploadedFile  Boolean?
  textSubtype      TextSubtype?
  labelAnnotations Json?
  webDetection     Json?
  imageProperties  Json?

  @@index([embeddedBlockId], type: Hash)
  @@index([embeddedPageId], type: Hash)
  @@index([userId], type: Hash)
  @@index([pageId], type: Hash)
}

enum ActivityType {
  FOLLOW
  SIGNUP
  BLOCK_CREATE
  PAGE_POSTED // a user posts a page/node
  PAGE_SHARED
  ADMIN_ANNOUNCEMENT // we admins throw something into everyone's feed
  BLOCK_OR_PAGE_LIKE
}

model Activity {
  id               String       @id @default(uuid())
  createdAt        DateTime     @default(now())
  type             ActivityType
  // default privacy control -- only followers can see activity.  Two overrides
  // (1) whether to make activity private even to followers
  isTotallyPrivate Boolean      @default(false)
  // (2) whether to make activity public even to non-followers
  isTotallyPublic  Boolean      @default(false)
  // user that did activity.  required
  userId           String
  user             User         @relation(fields: [userId], references: [id], onDelete: Cascade)
  // the user that was followed (only for FOLLOW action)
  userFollowedId   String?
  userFollowed     User?        @relation(name: "FollowActivity", fields: [userFollowedId], references: [id], onDelete: Cascade)
  // the block
  blockId          String?
  block            Block?       @relation(fields: [blockId], references: [id], onDelete: Cascade)
  // the page
  pageId           String?
  page             Page?        @relation(fields: [pageId], references: [id], onDelete: Cascade)

  // add indexes to make deleting on cascade fast

  @@index([userFollowedId], type: Hash)
  @@index([userId, id])
  @@index([userId], type: Hash)
  @@index([blockId], type: Hash)
  @@index([pageId], type: Hash)
  @@index([userFollowedId, createdAt(sort: Desc)])
}

model Page {
  id            String   @id @default(uuid())
  createdAt     DateTime @default(now())
  updatedAt     DateTime @updatedAt
  height        Int      @default(2000) // height in px of page canvas
  width         Int      @default(1200) // width in px of page canvas
  isSoftDeleted Boolean  @default(false)

  // for user relation
  userId String
  user   User   @relation(fields: [userId], references: [id], onDelete: Cascade)

  title      String
  blocks     Block[]
  isPublic   Boolean @default(false)
  isFeatured Boolean @default(false)
  isExample  Boolean @default(false)

  PageEmbeddings Block[]    @relation("EmbeddedPage")
  Activity       Activity[]

  permissionId String
  Permission   Permission @relation(fields: [permissionId], references: [id], onDelete: Cascade)

  screenshotTime DateTime?
  totalViews     Int       @default(0)

  likedBy  LikesOnUsers[]
  rawViews View[]

  @@unique([userId, title])
  @@index([userId], type: Hash)
}

model View {
  id        String   @id @default(uuid())
  createdAt DateTime @default(now())
  pageId    String
  viewerId  String? // might be undefined if not logged in user
  page      Page     @relation(fields: [pageId], references: [id], onDelete: Cascade)
  viewer    User?    @relation(fields: [viewerId], references: [id])
}

model Permission {
  id        String   @id @default(uuid())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  ownerId   String
  owner     User     @relation(fields: [ownerId], references: [id], onDelete: Cascade)
  editors   User[]   @relation("UserPermissions")
  pages     Page[]
}

model LikesOnUsers {
  id      String   @id @default(uuid())
  block   Block?   @relation(fields: [blockId], references: [id], onDelete: Cascade)
  blockId String?
  user    User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  userId  String
  page    Page?    @relation(fields: [pageId], references: [id], onDelete: Cascade)
  pageId  String?
  likedAt DateTime @default(now())

  @@unique([userId, blockId])
  @@unique([userId, pageId])
  @@index([userId], type: Hash)
  @@index([blockId], type: Hash)
  @@index([pageId], type: Hash)
}

// ////////////////// //
// SPLASH PAGE TABLES //
// ////////////////// //

model Agree {
  id           String   @id @default(uuid())
  updatedAt    DateTime @updatedAt
  title        String   @unique
  agreeCount   Int      @default(0)
  agreeReCount Int      @default(0)
}

model Waitlist {
  id        String   @id @default(uuid())
  updatedAt DateTime @updatedAt
  email     String   @unique
  firstName String
  lastName  String
  comment   String
  twitter   String?
  isInvited Boolean  @default(false)
}

model Quote {
  id       String     @id @default(uuid())
  text     String
  Response Response[]
}

model Response {
  id          String @id @default(uuid())
  text        String
  quoteId     String
  Quote       Quote  @relation(fields: [quoteId], references: [id])
  phoneNumber String
}

model FeatureFlags {
  id             String @id @default(uuid())
  rawViewScore   Int    @default(1)
  likedScore     Int    @default(1)
  pageEmbedScore Int    @default(1)
  halfLife       Int    @default(3)
}

Prisma Engine Query

  const user = await prismaDb.user.findUnique({
    where: { email },
    include: {
      followers: true,
      following: true,
      pages: { where: { isSoftDeleted: false }, include: { user: MINIMUM_USER_SELECT } },
      likedBlocksAndPages: {
        include: {
          page: {
            include: { user: MINIMUM_USER_SELECT },
          },
        },
      },
      editPermissions: {
        include: {
          pages: {
            where: { isSoftDeleted: false },
            include: { user: MINIMUM_USER_SELECT, Permission: { include: { editors: true } } },
          },
        },
      },
    },
  });
@jkomyno jkomyno added bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. tech/engines/query engine Issue in the Query Engine team/client Issue for team Client. tech/engines Issue for tech Engines. kind/bug A reported bug. and removed tech/engines/query engine Issue in the Query Engine labels Jun 1, 2022
@adomkg
Copy link

adomkg commented Jun 2, 2022

Hey @russellpekala did you find a solution for this one? Got the same error on my side

@janpio
Copy link
Member

janpio commented Sep 19, 2022

@adomkg @russellpekala @Epidimodev Any idea how we could reproduce this problem? Is it enough to take the schema above and somehow run the Prisma Client query that was provided in the initial message? What kind of data do we need in the database for this to be triggered?

@aqrln aqrln self-assigned this Oct 21, 2022
@aqrln
Copy link
Member

aqrln commented Oct 21, 2022

At first the only error I was able to get in Prisma 3.14 (after fixing the validation errors in the schema that prevented me from generating the client, and supposing that MINIMUM_USER_SELECT in the code means { select: { id: true } }) was this:

/Users/aqrln/prisma/prisma/reproductions/reproductions/gh-13585/node_modules/.prisma/client/runtime/index.js:45405
        throw new PrismaClientKnownRequestError(message, e.code, this.client._clientVersion, e.meta);
              ^
PrismaClientKnownRequestError: 
Invalid `prisma.user.findUnique()` invocation in
/Users/aqrln/prisma/prisma/reproductions/reproductions/gh-13585/index.ts:9:34

   6 async function main() {
   7   const prisma = new PrismaClient()
   8 
  9   const user = await prisma.user.findUnique(
  Failed to convert napi `string` into rust type `String`
    at Object.request (/Users/aqrln/prisma/prisma/reproductions/reproductions/gh-13585/node_modules/.prisma/client/runtime/index.js:45405:15)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async PrismaClient._request (/Users/aqrln/prisma/prisma/reproductions/reproductions/gh-13585/node_modules/.prisma/client/runtime/index.js:46301:18)
    at async main (/Users/aqrln/prisma/prisma/reproductions/reproductions/gh-13585/index.ts:9:16) {
  code: 'StringExpected',
  clientVersion: '3.14.0',
  meta: undefined
}

This is an error of completely different nature, so irrelevant to the original report, and it is not reproducible anymore with the latest Prisma. Also it was only reproducible on macOS but not on Linux.

However, after looking at the exact location where the panic happened it wasn't hard to see what the issue was.

This unwrap() in Tokio 1.15:
https://github.com/tokio-rs/tokio/blob/1f8105588c06c41c90c3c77628d10cde4b3b2edb/tokio/src/runtime/blocking/pool.rs#L247
is not present anymore since Tokio 1.18:
https://github.com/tokio-rs/tokio/blob/ebeb78ed40027032feb77c89a1de4b58d2dcafbf/tokio/src/runtime/blocking/pool.rs#L424

git blame shows that it was changed in tokio-rs/tokio#4485 to fix tokio-rs/tokio#2309 — which looks like exactly the same error you encountered.

Indeed, lowering the number of user processes from default on my Linux system 15334 down to 20, I got this panic in Prisma 3.14.0:

[aqrln@sparkles gh-13585]$ ulimit -u 20
[aqrln@sparkles gh-13585]$ ts-node index.ts
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }', /root/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.15.0/src/runtime/blocking/pool.rs:247:14
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fatal runtime error: failed to initiate panic, error 305979168
Aborted (core dumped)

(Note: this is a very contrived way to trigger the issue, the real world conditions under which it happened for you were probably very different. Under these artificial conditions even panic isn't able to work properly and the whole process crashes producing a core dump, while in your case Prisma was able to catch the panic, show a user-facing error on JavaScript side and exit gracefully).

When using the latest Prisma, this specific error doesn't happen anymore, because it is using Tokio 1.21.0. That said, there are all other kinds of things going wrong in different places when the limit is so small:

[aqrln@sparkles gh-13585]$ ulimit -u 20
[aqrln@sparkles gh-13585]$ ts-node index.ts
Error: read ENOTCONN
    at tryReadStart (node:net:659:20)
    at Socket._read (node:net:670:5)
    at Socket.Readable.read (node:internal/streams/readable:496:12)
    at Socket.read (node:net:725:39)
    at new Socket (node:net:446:12)
    at Object.Socket (node:net:315:41)
    at createSocket (node:internal/child_process:335:14)
    at ChildProcess.spawn (node:internal/child_process:450:23)
    at spawn (node:child_process:743:9)
    at Object.execFile (node:child_process:341:17) {
  errno: -107,
  code: 'ENOTCONN',
  syscall: 'read'
}
[aqrln@sparkles gh-13585]$ ulimit -u 30
[aqrln@sparkles gh-13585]$ ts-node index.ts
thread 'tokio-runtime-worker' panicked at 'timer has gone away', /root/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-timer-3.0.2/src/native/delay.rs:112:21
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
/home/aqrln/gh-13585/node_modules/.prisma/client/runtime/index.js:30881
      throw new PrismaClientRustPanicError(message, this.client._clientVersion);
            ^
PrismaClientRustPanicError:
Invalid `prisma.user.findUnique()` invocation in
/home/aqrln/gh-13585/index.ts:9:34

  6 async function main() {
  7   const prisma = new PrismaClient()
  8
→ 9   const user = await prisma.user.findUnique(
PANIC: timer has gone away

This is a non-recoverable error which probably happens when the Prisma Query Engine has a panic.

Please open an issue if you encounter any of these errors under real-world conditions after upgrading to the latest Prisma!

As for the original issue, since it is already fixed, I will go ahead and close this issue.

@aqrln aqrln closed this as completed Oct 21, 2022
@aqrln aqrln removed their assignment Oct 21, 2022
@aqrln aqrln added bug/2-confirmed Bug has been reproduced and confirmed. and removed bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. labels Oct 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug/2-confirmed Bug has been reproduced and confirmed. kind/bug A reported bug. team/client Issue for team Client. tech/engines Issue for tech Engines. topic: Failed to convert rust String into napi topic: postgresql
Projects
None yet
Development

No branches or pull requests

5 participants