Error: "user" defined in resolvers, but not in schema

Fluffy Ribbit picture Fluffy Ribbit · May 8, 2019 · Viewed 11k times · Source

I'm trying to set up my schema for Apollo Server, and I'm running into an error.

What I'm trying is actually an attempt to fix a common and even more unhelpful message, using advice found here:

https://github.com/apollographql/apollo-server/issues/1998

I'm not really sure how to reduce the code here, since I haven't been able to isolate the error more than this.

schema.js

import { makeExecutableSchema } from 'apollo-server-express'
import ApplicationSchema from './types'
import Resolvers from './resolvers'

export default makeExecutableSchema({
  typeDefs: ApplicationSchema,
  resolvers: Resolvers
})

resolvers/index.js

import user from './user'

export default {
  user
}

resolvers/user.js

import Joi from 'joi'
import mongoose from 'mongoose'
import { UserInputError } from 'apollo-server-express'
import { signUp, signIn } from '../validators'
import { User } from '../schemata' // mongoose schema
import * as Authentication from '../authentication'

export default {
  Query: {
    me: (root, args, { request }, info) => {
      Authentication.checkSignedIn(request)

      return User.findbyId(request.session.userId)
    },

    users: (root, args, { request }, info) => {
      Authentication.checkSignedIn(request)
      User.find({})
    },

    user: (root, args, { request }, info) => {
      const { id } = args

      Authentication.checkSignedIn(request)

      if (!mongoose.Types.ObjectId.isValid(id)) {
        throw new UserInputError(`${id} is not a valid user ID.`)
      }

      return User.findById(id)
    }
  },

  Mutation: {
    signup: async (root, args, { request }, info) => {
      Authentication.checkSignedOut(request)
      await Joi.validate(args, signUp, { abortEarly: false })
      return User.create(args)
    },

    signIn: async (root, args, { request }, info) => {
      const { userId } = request.session

      if (userId) return User.findById(userId)

      await Joi.validate(args, signIn, { abortEarly: false })

      const user = await Authentication.attemptSignIn(args)

      request.session.userId = user.id

      return user
    },

    signOut: async (root, args, { request, response }, info) => {
      Authentication.checkSignedIn(request)

      return Authentication.signOut(request, response)
    }
  }
}

types/index.js

import root from './root'
import user from './user'

export default [
  root, 
  user
]

types/root,js

import { gql } from 'apollo-server-express'

export default gql`
 type Query {
   _: String
 }

 type Mutation {
   _: String
 }

 type Subscription {
   _: String
 }

types/user.js

import { gql } from 'apollo-server-express'

export default gql`
  type User {
    id: ID!
    email: String!
    username: String!
    name: String!
    password: String!
    createdAt: String!
  }

  extend type Query {
    me: User
    user(id: ID!): User
    users: [User!]!
  }

  extend type Mutation {
    signUp(email: String!, username: String!, name: String!): User
    signIn(email: String!, password: String!): User
    signOut: Boolean
  }

Hopefully, schema.js should run without errors and the resulting executable schema will work well with Apollo Server.

Answer

Daniel Rearden picture Daniel Rearden · May 9, 2019

Your resolvers object should be structured like what's inside types/user.js, i.e.:

{
  Query: {
    // Query fields
  },
  Mutation: {
    // Mutation fields
  },
  // etc.
}

The resolvers object should be a map of type names. Instead, because of the way your imports are set up, you're ending up with:

{
  user: {
    Query: {
      // Query fields
    },
    Mutation: {
      // Mutation fields
    },
    // etc.
  }
}  

Because this is what you're passing in as your resolvers, Apollo assumes you're trying to map resolvers for a type called user, which doesn't exist in your schema, so it throws the error you're seeing.

If you want to combine multiple resolver objects, you need to recursively merge them using something like lodash's merge:

import user from './user'
import foo from './foo'
import _ from 'lodash'

export default _.merge(
  user,
  foo
)