bouhm
bouhm

Reputation: 55

GraphQL "Schema must contain uniquely named types" when using Serverless

I'm trying to deploy a NestJS GraphQL API server with Serverless and AWS Lambda. When running the app locally I am able to use the GraphQL playground without any issues, but when running Serverless offline I get the following error:

Error: Schema must contain uniquely named types but contains multiple types named "Constellation".

The error states that ObjectTypes Constellation and Affix are not unique. These are both ObjectTypes that represent the type for a field:

MODEL SCHEMAS

// character.model.ts

import mongoose, { Document, Schema as MongooseSchema } from 'mongoose';

import { Field, ObjectType } from '@nestjs/graphql';
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';

@ObjectType('Constellation')
class Constellation {
  @Field(() => String)
  effect: string;

  @Field(() => Number)
  oid: number;

  @Field(() => String)
  name: string;

  @Field(() => Number)
  pos: number;

  @Field(() => String)
  icon: string;
}

@ObjectType()
@Schema({ timestamps: true })
export class Character {
  @Field(() => String)
  _id: MongooseSchema.Types.ObjectId;

  @Field(() => Number)
  @Prop({ required: true, unique: true })
  oid: number;

  @Field(() => [Constellation])
  @Prop({ required: true })
  constellations: Constellation[];

  @Field(() => String)
  @Prop({ required: true })
  element: string;

  @Field(() => String)
  @Prop({ required: true })
  name: string;

  @Field(() => Number)
  @Prop({ required: true })
  rarity: number;

  @Field(() => String)
  @Prop({ required: true })
  icon: string;

  @Field(() => String)
  @Prop({ required: true })
  image: string;
}

export type CharacterDocument = Character & Document;
export const CharacterSchema = SchemaFactory.createForClass(Character);
export default mongoose.model<CharacterDocument>(Character.name, CharacterSchema);
// artifact-set.model.ts

import mongoose, { Document, Schema as MongooseSchema } from 'mongoose';

import { Field, ObjectType } from '@nestjs/graphql';
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';

@ObjectType('Affix')
export class Affix {
  @Field(() => Number)
  activation_number: number;

  @Field(() => String)
  effect: string;
}

@ObjectType()
@Schema({ timestamps: true })
export class ArtifactSet {
  @Field(() => String)
  _id: MongooseSchema.Types.ObjectId;

  @Field(() => Number)
  @Prop({ required: true, unique: true })
  oid: number;

  @Field(() => [Affix])
  @Prop({ required: true })
  affixes: Affix[];

  @Field(() => String)
  @Prop({ required: true })
  name: string;
}

export type ArtifactSetDocument = ArtifactSet & Document;
export const ArtifactSetSchema = SchemaFactory.createForClass(ArtifactSet);
export default mongoose.model<ArtifactSetDocument>(ArtifactSet.name, ArtifactSetSchema);

IMPORTS

Since I've seen that importing these models could be a source of the problem, I've also included an example import:

import { Affix, ArtifactSet } from '../artifact-set/artifact-set.model';

This is imported into a service file in ../character/character.service for another model, and is not imported elsewhere. The Constellation ObjectType is not explicitly imported anywhere else, yet is the first type to raise an error.

serverless.yml

app: server
service: server-api
useDotenv: true

package:
  patterns:
    - '!dist/**'
    - '!src/seeds/**'

plugins:
  - serverless-plugin-typescript
  - serverless-offline

# custom:
#   serverless-offline:
#     allowCache: true

provider:
  name: aws
  profile: serverless-admin
  runtime: nodejs12.x
  lambdaHashingVersion: 20201221

functions:
  main:
    handler: src/lambda.handler
    events:
      - http:
          path: graphql
          method: POST
          cors: true
          integration: LAMBDA
      - http:
          path: graphql
          method: GET
          cors: true
          integration: LAMBDA
      - http:
          path: playground
          method: ANY
          cors: true
          integration: LAMBDA

ATTEMPTS

I've tried the following based on research of users facing similar problems:

  1. Double check that imports have no typos, are all same case
  2. Change class name, specify name within decorator (ex. ObjectType('Constellation')
  3. Change imports to use absolute path (src/../..)
  4. Use types/interfaces instead of ObjectType
  5. Remove the mongoose default export from schemas

Upvotes: 3

Views: 1118

Answers (1)

pope12
pope12

Reputation: 86

I can't be sure this was your issue, but I had the same error while using nest, and serverless-offline.

What solved it for me was adding --allowCache to the serverless offline command. See Docs

npx serverless offline --allowCache

Without that, my server variable was not being cached, but somehow the OrphanedReferenceRegistry was being cached between function calls. Each time I hit my URL my server was bootstrapped again, my ObjectType was added to the existing registry, which triggered the error when the schema was created because there were 2+ of the same ObjectType.

Here are my notes for reference in case it helps anyone with a similar issue https://github.com/pope-12/nest-graphql-serverless-error

Upvotes: 2

Related Questions