Prisma-client-js: Error in Photon when where object is empty

Created on 16 Jul 2019  路  10Comments  路  Source: prisma/prisma-client-js

I have modified the generated sample to test using where clausule on backward relation of relation.

However it just fails then the where clause is empty as I have to pass where object to the findOne method:

  const postsByUser = await photon.users.findOne({
    where: {},
    select: {
      name: true,
      email: true,
      posts: {
        select: {
          title: true,
          published: true
        }
      }
    }
Error: Error in Photon:
thread 'arbiter:1dc8d033-d2a7-4165-b64d-0a8361984814:actix-net-worker-2' panicked at 'object was empty', src/libcore/option.rs:1034:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
   1: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:71
   2: std::panicking::default_hook::{{closure}}
             at src/libstd/sys_common/backtrace.rs:59
             at src/libstd/panicking.rs:197
   3: std::panicking::default_hook
             at src/libstd/panicking.rs:211
   4: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:474
   5: std::panicking::continue_panic_fmt
             at src/libstd/panicking.rs:381
   6: rust_begin_unwind
             at src/libstd/panicking.rs:308
   7: core::panicking::panic_fmt
             at src/libcore/panicking.rs:85
   8: core::option::expect_failed
             at src/libcore/option.rs:1034
   9: core::builders::utils::extract_record_finder
  10: <core::builders::one::OneBuilder as core::builders::BuilderExt>::build
  11: core::builders::Builder::build
  12: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &mut F>::call_once
  13: <&mut I as core::iter::traits::iterator::Iterator>::next
  14: <alloc::vec::Vec<T> as alloc::vec::SpecExtend<T,I>>::from_iter
  15: core::builders::root::RootBuilder::build_query
  16: core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &mut F>::call_once
  17: <&mut I as core::iter::traits::iterator::Iterator>::next
  18: <alloc::vec::Vec<T> as alloc::vec::SpecExtend<T,I>>::from_iter
  19: core::builders::root::RootBuilder::build
  20: <prisma::req_handlers::graphql::GraphQlRequestHandler as prisma::req_handlers::RequestHandler>::handle
  21: prisma::http_handler
  22: <F as actix_web::with::FnWith<T,R>>::call_with
  23: <actix_web::with::WithHandlerFut<T,S,R> as futures::future::Future>::poll
  24: actix_web::pipeline::PipelineState<S,H>::poll
  25: <actix_web::pipeline::Pipeline<S,H> as actix_web::server::handler::HttpHandlerTask>::poll_io
  26: actix_web::server::h1::Http1Dispatcher<T,H>::poll_handler
  27: actix_web::server::h1::Http1Dispatcher<T,H>::poll
  28: <actix_web::server::channel::HttpChannel<T,H> as futures::future::Future>::poll
  29: <actix_web::server::channel::HttpChannel<T,H> as futures::future::Future>::poll
  30: <actix_net::service::and_then::AndThenFuture<A,B> as futures::future::Future>::poll
  31: futures::future::chain::Chain<A,B,C>::poll
  32: futures::task_impl::std::set
  33: futures::task_impl::Spawn<T>::poll_future_notify
  34: tokio_current_thread::CurrentRunner::set_spawn
  35: tokio_current_thread::scheduler::Scheduler<U>::tick
  36: tokio_current_thread::Entered<P>::block_on
  37: std::thread::local::LocalKey<T>::with
  38: std::thread::local::LocalKey<T>::with
  39: std::thread::local::LocalKey<T>::with
  40: std::thread::local::LocalKey<T>::with
  41: tokio::runtime::current_thread::runtime::Runtime::block_on

    at PhotonFetcher.<anonymous> (/usr/app/node_modules/@generated/photon/index.js:37:23)
    at Generator.throw (<anonymous>)
    at rejected (/usr/app/node_modules/@generated/photon/index.js:5:65)
    at processTicksAndRejections (internal/process/task_queues.js:85:5)
bu2-confirmed kinbug

Most helpful comment

To sum up our latest findings:
This issue is unrelated to the findOrNull issue.

The Rust implementation incorrectly crashes when providing where: {}, because it can't parse that statement. This is not intended and will be fixed as soon as we merge a rewrite of that part of the query engine in the coming 1-2 weeks.

About where: {} and PhotonJS: Both findOne and findMany should return a nice error when where is completely empty.
While where: {} is in itself a valid statement, the reason we want to throw here is to inform the user that it's an empty statement, showing all possible options.

And the last important thought here: We'll allow where: {field: undefined}. Why? If you're constructing a where argument programmatically, you'll easily end up in that situation, that something may be undefined.

The progress of allowing a where argument, where all values are undefined is being tracked here https://github.com/prisma/photonjs/issues/152

All 10 comments

@19majkel94 I think this issue is related to the one being discussed at #89 Add findOrNull method

The error is thrown by findOne because where: {} does not find any records.

Please have a look at #89 and comment over there.

The error is thrown by findOne because where: {} does not find any records.

I agree but if I don't provide where property, I receive nice colorful error about it. When I provide empty object, I receive a stacktrace from rust kernel panic. This issue is about helpful errors, like "The error is thrown by findOne because where: {} does not find any records." 馃槈

This issue is about helpful errors

OK, I agree, helpful errors are vital. The real error 'object was empty', would be much more useful if it was presented on its own line, rather than buried in the noise.

Some details are omitted, run with RUST_BACKTRACE=full for a verbose backtrace.

Implies that there is more?!

However, Rust docs say

Let鈥檚 try getting a backtrace by setting the RUST_BACKTRACE environment variable to any value except 0

I suspect RUST_BACKTRACE is already enabled. I tried setting an environment variable RUST_BACKTRACE=0 but that didn't make a difference.

The issue stands. We need more readable, more concise error messages.

@19majkel94

This is expected in my opinion. If you omit parameter where parameter from findOne it defeats its purpose. You can surely omit where in the findMany method. FindOne method is used for finding a record that matches the unique value. That is why even non-unique fields are not available inside it.

I think the problem here is with typing. We should not allow where: {} in findOne.

So I think you should use the following code:

 const data = await photon.users.findMany({
    select: {
      name: true,
      email: true,
      posts: {
        select: {
          title: true,
          published: true,
        },
      },
    },
  })

If you omit parameter where parameter from findOne it defeats its purpose.

What about selecting the first record? E.g. the user with the highest score field:

model User {
  name  String
  score Int
}
const topPlayer = await photon.users.findOne({
  order: {
    score: "DESC",
  }
});

const [topPlayer] = await photon.users.findMany({
  order: {
    score: "DESC",
  },
  limit: 1,
})

Score is not a unique property here. There is possibility that two records can have same score which can be the highest score. So really there is possiblity of returning more than one record here. So #2 makes more sense

Sure the error is expected/justified but as @19majkel94 commented earlier:

This issue is about helpful errors, like "The error is thrown by findOne because where: {} does not find any records."

The error as thrown is a huge mess, especially as it appears in the Playground.

It would be wonderful if the error as in the OP could be reduced to:

Error: Error in Photon: 'object was empty'

That's really the only relevant information for the developer using Photon.

Can we avoid sending the whole backtrace to the client?

We are working on a error handling spec right now: https://github.com/prisma/specs/blob/errors/errors/Readme.md

It will get implemented in the coming weeks.

To sum up our latest findings:
This issue is unrelated to the findOrNull issue.

The Rust implementation incorrectly crashes when providing where: {}, because it can't parse that statement. This is not intended and will be fixed as soon as we merge a rewrite of that part of the query engine in the coming 1-2 weeks.

About where: {} and PhotonJS: Both findOne and findMany should return a nice error when where is completely empty.
While where: {} is in itself a valid statement, the reason we want to throw here is to inform the user that it's an empty statement, showing all possible options.

And the last important thought here: We'll allow where: {field: undefined}. Why? If you're constructing a where argument programmatically, you'll easily end up in that situation, that something may be undefined.

The progress of allowing a where argument, where all values are undefined is being tracked here https://github.com/prisma/photonjs/issues/152

Another update:
It's important to note, that the where for findOne must not be empty, whereas the where for findMany can be empty.

Therefore we added error handling for empty where statements for findOne, but removed it for findMany.

A separate issue is, that as of now the query engine can't handle empty where arguments in findMany statements. The progress of that is being tracked in https://github.com/prisma/photonjs/issues/165

Was this page helpful?
0 / 5 - 0 ratings