GraphQL-Error: Found Duplicate Type Names: Cat

2 replies
Last updated: Jul 30, 2020
Hi, I’m trying to move a Sanity project to use GraphQL, and I encountered an issue when I tried to deploy the GraphQL-schema. It appears there’s a generated GraphQL union type that ends up having the same name as another type.
I’ve reconstructred the issue in a minimal schema.js, where I have a person document that can have an array of cats. The cats can be created as part of the person document, or as a reference.


import createSchema from "part:@sanity/base/schema-creator";
import schemaTypes from "all:part:@sanity/base/schema-type";

const cat = {
    title: 'Cat',
    name: 'cat',
    type: 'document',
    fields: [
        {
            title: 'Name',
            name: 'name',
            type: 'string'
        }
    ]
};

const person = {
    title: 'Person',
    name: 'person',
    type: 'document',
    fields: [
        {
            title: 'Name',
            name: 'name',
            type: 'string'
        },
        {
            title: 'Cats',
            name: 'cats',
            type: 'array',
            of: [
                {
                    type: 'reference',
                    title: 'Cat Reference',
                    to: [{ type: 'cat' }]
                },
                { type: 'cat' }
            ],
        }
    ]
};

export default createSchema({
    name: "default",
    types: schemaTypes.concat([ cat, person ])
});
This code breaks when you run
sanity graphql deploy
with the error message: “Error: Found duplicate type names: Cat”.
I have found a workaround for this issue that works, but it’s not ideal and I’m looking for a better solution.
AI Update

This is a known issue with Sanity's GraphQL schema generation that occurs when you try to use the same type both as a document type (for standalone documents that can be referenced) and as an inline object type within an array. When GraphQL generates the schema, it creates a union type for the array that conflicts with the document type name, resulting in the "Found duplicate type names: Cat" error.

The Root Cause

The problem happens because you're using cat in two different ways in your schema:

  1. As a standalone document type that can be referenced
  2. As an inline object within the cats array in the person document

When you include both { type: 'reference', to: [{ type: 'cat' }] } and { type: 'cat' } in the same array, GraphQL tries to create a union type named "Cat" for the array items, but that name already exists as the document type.

The Recommended Solution

Create separate types for the document and the inline object. Here's the cleanest approach:

import createSchema from "part:@sanity/base/schema-creator";
import schemaTypes from "all:part:@sanity/base/schema-type";

// Shared fields that both types will use
const catFields = [
  {
    title: 'Name',
    name: 'name',
    type: 'string'
  }
];

// Document type for standalone cat documents
const cat = {
  title: 'Cat',
  name: 'cat',
  type: 'document',
  fields: catFields
};

// Object type for inline cats
const catObject = {
  title: 'Cat (Inline)',
  name: 'catObject',
  type: 'object',
  fields: catFields
};

const person = {
  title: 'Person',
  name: 'person',
  type: 'document',
  fields: [
    {
      title: 'Name',
      name: 'name',
      type: 'string'
    },
    {
      title: 'Cats',
      name: 'cats',
      type: 'array',
      of: [
        {
          type: 'reference',
          title: 'Cat Reference',
          to: [{ type: 'cat' }]
        },
        { type: 'catObject' }  // Use the separate object type
      ],
    }
  ]
};

export default createSchema({
  name: "default",
  types: schemaTypes.concat([cat, catObject, person])
});

This approach gives you the functionality you want (both referencing existing cats and creating inline cats) without the naming conflict. The inline cats created with catObject will only exist within the person document, while cat documents remain globally available and referenceable.

About Your Workaround

Your workaround of adding a dummy workaround type to the reference array is clever! By making the reference point to multiple types [{ type: 'cat' }, { type: 'workaround' }], you force GraphQL to generate a different union type name like "CatOrWorkaround" instead of just "Cat", which avoids the naming collision. While it works, the separate object type approach above is cleaner and more semantically correct.

Important Note About Creating References

It's worth mentioning that Sanity doesn't currently support creating new referenced documents directly from within another document's reference field (sometimes called "creating references in place"). When you use a reference field, you can only select from existing documents. The inline object approach creates data within the parent document itself, not as a separate referenceable document.

If you need the ability to create new standalone cat documents that can be referenced elsewhere, users will need to create those separately in the Studio first, then reference them in the person document.

As for the details of the workaround:
If you change the cat reference to refer to either a cat or some other type, the generated name will change and there’s no longer a duplicate name. In my case, it changes from Cat to CatOrWorkaround. Additionally I made the workaround document always validate to an error.

The code looks like this:


import createSchema from "part:@sanity/base/schema-creator";
import schemaTypes from "all:part:@sanity/base/schema-type";

const cat = {
    title: 'Cat',
    name: 'cat',
    type: 'document',
    fields: [
        {
            title: 'Name',
            name: 'name',
            type: 'string'
        }
    ]
};

const workaround = {
    title: 'Workaround',
    name: 'workaround',
    type: 'document',
    fields: [
        {
            title: 'Name',
            name: 'name',
            type: 'string'
        }
    ],
    validation: Rule => Rule.required().custom(() =>
        "Do not create a Workaround document. " +
        "The Workaround document fixes a naming issue when deploying the GraphQL schema."
    )
};

const person = {
    title: 'Person',
    name: 'person',
    type: 'document',
    fields: [
        {
            title: 'Name',
            name: 'name',
            type: 'string'
        },
        {
            title: 'Cats',
            name: 'cats',
            type: 'array',
            of: [
                {
                    type: 'reference',
                    title: 'Cat Reference',
                    to: [{ type: 'cat' }, { type: 'workaround' }]
                },
                { type: 'cat' }
            ],
        }
    ]
};

export default createSchema({
    name: "default",
    types: schemaTypes.concat([ cat, person, workaround ])
});
That’s a pretty clever workaround, Tommy 🙂 The issue is occurring because you’re using the
cat
type both as a
document
type (referencing stand-alone docs) and as an
object
type, where creating a cat inside the
person
document will not actually create a new
cat
document but an in-line cat object in the
cats
array.
Generally speaking, we do not yet have a functionality to create new documents from within a different document, in other words: creating references in place. This is very much on our radar as a feature request though.

As an alternative workaround, you could include the reference to
cat
as you already do, but then create a separate cat object type in addition to the cat document type you already have. Let’s call it
catObject
for this purpose. You should then be able to both reference cats (available globally) and create new cats locally in the document (not available globally).
Hope the above explanation is clear enough - happy to give more context!

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?