Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

error in typeMapReducer causes graphql to fail on certain schemas #2439

Closed
narration-sd opened this issue Feb 7, 2020 · 7 comments
Closed
Labels

Comments

@narration-sd
Copy link

narration-sd commented Feb 7, 2020

This error exists in both 14.x and 15.x branches, and has a one-line tested fix, so presenting that here rather than in multiple pull requests.

Issue:

In either branch latest, graphql fails immediately for certain schemas, reporting:
Error: Schema must contain uniquely named types but contains multiple types named "Name"
where for my schema Name may be PageInfo or Mutation.

Others have reported similar problems, also for graphql as used in Gridsome.

Response:

Tracking this down via the stack trace and logging, the problem is that function typeMapReducer() in type/schema.js is doing a compare of objects for the Type name, to determine failure.

  if (seenType) {
    if (seenType !== namedType) {
      throw new Error("Schema must contain uniquely named types but contains multiple types named \"".concat(namedType.name, "\"."));
    }
...

Adding a cast to String before comparing solves this. The code becomes:

  if (seenType) {
    if (String(seenType) !== String(namedType)) {
      throw new Error("Schema must contain uniquely named types but contains multiple types named \"".concat(namedType.name, "\"."));
    }
...

This code appears at apparent lines 338 in type/schema.js source for 14.x, and 319 in 15.x source, as these appear on this github repo.

It seems both branches should be repaired with fresh release, especially14.x, as many are using that in the field. Thanks.

Rationale:

The commonality for the PageInfo and Mutation terms that fail with present code is that they appear in multiple graphql Connections.

It's possible that the uniqueness test really does intend to compare objects, but that the situation is complicated by the fact that in Gridsome (also potentially in Gatsby, perhaps others), there are data-source-resolving prefixes added to the actual declaration of some terms, which arrive early in the map array for typeMapReducer().

I'm attaching a log of that map array, as in use at the point where the failure occurs. so you can see the use of prefixes.

If the prefixes are the problem, then this 'fix' becomes a workaround, until a proper design can accomodate.

map.zip

@narration-sd
Copy link
Author

...reflected a little more on what seems to be intended by typeMapReducer's check, so updated the issue statement, if you read early by email.

@IvanGoncharov
Copy link
Member

reflected a little more on what seems to be intended by typeMapReducer's check, so updated the issue statement, if you read early by email.

@narration-sd Yes, you absolutely correct it's intentional.
String(seenType) !== String(namedType) will never be false since seenType is found by name.
This error typically happens when you have duplicating packages in your node_modules please ensure that npm ls graphql-relay returns only one package.

@narration-sd
Copy link
Author

Ivan, thanks indeed for coming back so quickly.

I checked for duplicating packages; graphql-relay isn't present at all, and for alll other graphql*, the only indications of duplication were apparently references in the build parts of other packages: no actual duplicate module present so far as I could see, save one I'd already removed of graphql itself within the gridsome module.

So, I dumped out more of what typeMapReducer() is dealing with as initialTypes -- and, the initiating schema from the server, at least a reasonable facsimile.

  • actually the call to function GraphQLSchema(config) occurs six times...for reasons I haven't delved to be clearer about
  • but the last call deals with the largest set of items in initialTypes, attached as initialTypes.last.js, and indeed it contains duplicates of PageInfo and Mutation, which are what your proper compare, if allowed, will recognize.
  • however, the initiating schema has apparently only one Object definition for either PageInfo or Mutation, as you can find in attached agr.introspect.json. This is from a fairly formidable introspection query I've picked up from another tool.

So, I think the problem actually has to be on the Gridsome side, and perhaps specifically in some operations that are done in its connector to over-the-wire GraphQL servers. They're from a standardd library, but maybe there's something about how the calls are being applied that's allowing the doubling up. A clue for that is maybe finding the duplicate types near the end of agr.introspect.json; we'll have to see.

If you have any ideas, most welcome of course.

  • for completeness, I also dumped the full map that typeMapReducer() produces if I block it from exceptioning on the duplicates. Interestingly it has no duplicates even without the check, as you might expect from the code, and indeed the overall systems seems to work fine: my app is produced and functions, though it doesn't actually use either PageInfo or Mutation. I read earlier about Relay being stiff about duplicate definitions, and maybe the trouble would show up if indeed graphql-relay were in play here, as it is not.

Again, much appreciation for your clear, immediate, and helpful response, Ivan.

Best,
Clive

initialTypes.last.zip
agr.introspect.zip
full-map.zip

@IvanGoncharov
Copy link
Member

@narration-sd If you can modify source code of graphql package you can add this line:

class GraphQLObjectType {
  constructor(...) {
    ...
    this.stackTrace = String(new Error().stack);
    ...
  }
}

and print stackTrace of conflicting types it will give you a clue where they were contstructed.
If it's not duplicating packages the second most popular cause is when you try to do schema transformation and don't properly update types.

@narration-sd
Copy link
Author

Thanks - that output's quite useful. Hadn't realized a stack trace could be had so easily...

A good weekend to you, spasibo

@narration-sd
Copy link
Author

@IvanGoncharov , this is all sorted now, and reported for a close, over at the Gridsome issue.

It turns out I had an extra source added, in some well-hidden outdated configuration for an early, superseded plugin someone once built for them. This managed to merge the same remote schema, accurately, but without the prefixing, thus your preflight was quite correct in picking off the problem.

The stack traces were essential, in getting orders right, and thus arriving at this.

@sibelius
Copy link

sibelius commented Jun 7, 2022

how did you figure it out?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants