Search code examples
mongodbmongoosegraphqlmongoose-schema

How to fix constructor error in GraphQL Mutation with Mongoose Schema


Having a lot of trouble with a GraphQL mutation Mongoose error for validating if a user is new or existing in MongoDB. Per the code below the error message is "message": "User is not a constructor".

A similar issue is here, and I redefined the variable below given each method in the solution to that linked issue with similar errors - only change in error was due to lacking constructor such as when I used other methods like append the error is "User is undefined".

CodeSandbox with all the code: https://codesandbox.io/s/apollo-server-sh19t?fontsize=14

The code in question is:


var userSchema = new mongoose.Schema({
  username: {
    type: String,
    required: true,
    unique: true
  },
  email: {
    type: String,
    required: true,
    trim: true
  },
  password: {
    type: String,
    required: true,
    trim: true
  },
  avatar: {
    type: String
  },
  joinDate: {
    type: Date,
    default: Date.now
  },
  favorites: {
    type: [mongoose.Schema.Types.ObjectId],
    required: true,
    ref: "Post"
  }
});

// compile model
var User = mongoose.model("User", userSchema);

var getUserModel = function() {
  return mongoose.model("User", userSchema);
};

Mutation: {
    signupUser: async (_, { username, email, password }, { User }) => {
      let user = await getUserModel().findOne({ username });
      if (user) {
        throw new Error("Please choose another username");
      }
      const newUser = await new User({
        username,
        email,
        password
      }).save();
      return newUser;
    }
  }
};

The full error is:

{
  "errors": [
    {
      "message": "User is not a constructor",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "signupUser"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "stacktrace": [
            "TypeError: User is not a constructor",
            "    at signupUser (/xxx/xxx/xxx/servers.js:175:29)",
            "    at process._tickCallback (internal/process/next_tick.js:68:7)"
          ]
        }
      }
    }
  ],
  "data": null
}
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "signupUser"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "stacktrace": [
            "TypeError: Cannot read property 'create' of undefined",
            "    at signupUser (/xxxx/xxxx/xxx/servers.js:175:38)"

Any assistance to this issue would be greatly appreciated.


Solution

  • That TypeError is thrown any time you try to use the new keyword with something that's not a constructing, including an undefined value. Even if you define a User variable outside of the constructor, you're still shadowing that variable because you're destructuring the context parameter and declaring a User variable that way. If you're not passing the User model to your context correctly, attempting to get the value from the context will result in the value being undefined. Either fix the context or don't unnecessarily destructure it.