Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prisma API returns relation but client returns "cannot return null for non-nullable field.."

When I try to return fields from a one-to-many relation in Prisma client playground it returns the following error:

Cannot return null for non-nullable field DeviceConfig.device.

What in my resolver or client could be causing this?

When running the following query on the backend Prisma API playground it does return the correct data so that tells me my mutations and relationship is good.

Datamodel

type Device {
  ...
  model: String! @unique
  ...
  configs: [DeviceConfig] @relation(name: "DeviceConfigs", onDelete: CASCADE)
}

type DeviceConfig {
  id: ID! @unique
  device: Device! @relation(name: "DeviceConfigs", onDelete: SET_NULL)
  name: String!
  ...
}

Resolver

deviceConfig: async (parent, { id }, context, info) => context.prisma.deviceConfig({ id }, info)

Query

{
  deviceConfig(id:"cjqigyian00ef0d206tg116k5"){
    name
    id
    device{
      model
    }
  }
}

Result

{
  "data": null,
  "errors": [
    {
      "message": "Cannot return null for non-nullable field DeviceConfig.device.",
      "locations": [
        {
          "line": 5,
          "column": 5
        }
      ],
      "path": [
        "deviceConfig",
        "device"
      ]
    }
  ]
}

I expect the query to return the model of the device like the backend Prisma API server does Query

{
  deviceConfig(where:{id:"cjqigyian00ef0d206tg116k5"}){
    name
    id
    device{
      id
      model
    }
  }
}

Result

{
  "data": {
    "deviceConfig": {
      "name": "Standard",
      "id": "cjqigyian00ef0d206tg116k5",
      "device": {
        "id": "cjqigxzs600e60d20sdw38x7p",
        "model": "7530"
      }
    }
  }
}
like image 423
GerritVK Avatar asked Jan 04 '19 23:01

GerritVK


2 Answers

This forum post helped me understand some caveat around Prisma client when it comes to resolvers. Help Understanding Prisma Client’s Value Proposition

In my case I was missing the following revolvers because I thought they would be implied based on the schema relationship.

const resolvers = {
  // Relationship resolvers
  Device: {
    configs: (parent, args, context) => context.prisma.device({ id: parent.id }).configs(),
  },
  DeviceConfig: {
    device: (parent, args, context) => context.prisma.deviceConfig({ id: parent.id }).device(),
  },
  Query: {
    ...User.Query,
    ...Device.Query,
    ...DeviceConfig.Query,
  },
  Mutation: {
    ...User.Mutation,
    ...Device.Mutation,
    ...DeviceConfig.Mutation,
  },
};
like image 178
GerritVK Avatar answered Oct 18 '22 13:10

GerritVK


I think you are mixing Prisma Bindings syntax with Prisma Client syntax.

The info object is something you pass to the bindings to return what the user is asking for. However, this feature is not available in the Prisma Client, which you seem to be using. If you need that feature then you could try Prisma Bindings.

Otherwise, modify your code to something like context.prisma.deviceConfig({ id }).device(). I think it can also accept a fragment context.prisma.deviceConfig({ id }).$fragment('fragment configWithDevice on DeviceConfig { id name device { id model } }').

like image 41
Fran Dios Avatar answered Oct 18 '22 14:10

Fran Dios