prisma/prisma

Error Thrown When Sorting Field Is Not Selected

Hellio404 opened this issue · 3 comments

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

Versions

Name Version
Node v20.10.0
OS darwin-arm64
Prisma Client 5.3.1
Query Engine 61e140623197a131c2a6189271ffee05a7aa9a59
Database sqlserver

Logs

PrismaClientRustPanicError:
Invalid `client.post.findMany()` invocation in
/build/index.js

  61         })];
  62 case 1:
  63     id = (_a.sent()).id;
→ 64     return [4 /*yield*/, client.post.findMany(
no entry found for key

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

Client Snippet

  await client.user.create({
    data: {
      posts: {
        createMany: {
          data: Array(4000).fill({title: 'post'}),
        }
      }
    }
  });

  await client.post.findMany({
    where: { authorId: { in: Array.from(Array(4000).keys()) }},
    select: {id: true, title: true},
    orderBy: {createdAt: 'asc'},
  });

Schema

// PLEASE ADD YOUR SCHEMA HERE IF POSSIBLE
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider          = "sqlserver"
  url               = env("DATABASE_URL")
  shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
}

model User {
  id       Int      @id @default(autoincrement())
  posts    Post[]
}

model Post {
  id        Int    @id @default(autoincrement())
  title     String
  author    User   @relation(fields: [authorId], references: [id])
  authorId  Int
  createdAt DateTime @default(now())
}

Description

I've noticed that whenever a query is split (due to the maximum parameter constraint of 2100 in SQL Server), Prisma attempts to perform an in-memory sort.
However, if the field being sorted is not selected, an error is thrown.

To fix this issue, I had to always include the field used for sorting in the selected fields.

Druue commented

Hey @Hellio404, I can confirm the ""2100 parameters"" error message but I can't confirm the resolution by including the createdAt: true in the select, neither on dev nor on 5.3.1.

await prisma.post.findMany({
  where: { authorId: { in: Array.from(Array(4000).keys()) } },
-  select: { id: true, title: true },
+  select: { id: true, title: true, createdAt: true },
  orderBy: { createdAt: 'asc' },
});

Could you please provide a reproduction that shows this succeeding with the inclusion of createdAt in select

@Druue

I double checked and I confirm that adding the createdAt: true fixes the issue for me as well as removing select all together

  const { id } = await client.user.create({
    data: {
      posts: {
        createMany: {
          data: Array(4000).fill({title: 'post'}),
        }
      }
    }
  });
  // this works
  const sortedPosts = await client.post.findMany({
    where: { authorId: { in: Array.from(Array(4000).keys()) }},
    select: {id: true, title: true, createdAt: true},
    orderBy: {createdAt: 'asc'},
  });
  // this works too
  await client.post.findMany({
    where: { authorId: { in: Array.from(Array(4000).keys()) }},
    orderBy: {createdAt: 'asc'},
  });
Druue commented

Huh, I double checked in another repro repo and I can reproduce it there. You can see a link above. For some reason, however, I still cannot reproduce this in our internal reproductions dir that directly hooks into a locally-built version of the client. I have no idea what's going on there :/

Looking at the succeeding findMany query that includes createdAt: true, I see following two (minimised) SQL queries logged.

SELECT [dbo].[Post].[id], [dbo].[Post].[title], [dbo].[Post].[createdAt]
FROM [dbo].[Post]
WHERE [dbo].[Post].[authorId] IN (@P1 ... @P2098)

SELECT [dbo].[Post].[id], [dbo].[Post].[title], [dbo].[Post].[createdAt]
FROM [dbo].[Post]
WHERE [dbo].[Post].[authorId] IN (@P1 ... @P1902)

If I swap to the failing query that doesn't include createdAt: true, I see the following logged

SELECT [dbo].[Post].[id], [dbo].[Post].[title]
FROM [dbo].[Post]
WHERE [dbo].[Post].[authorId] IN (@P1 ... @P2098)

with the following error:

thread 'tokio-runtime-worker' panicked at query-engine/query-structure/src/record.rs:69:46:
no entry found for key
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

This is the relevant code that it references

and then the following SQL query after:

SELECT [dbo].[Post].[id], [dbo].[Post].[title]
FROM [dbo].[Post]
WHERE [dbo].[Post].[authorId] IN (@P1 ... @P1902)