From b5b43d513ec7e73b52462dd80ed160625be67f89 Mon Sep 17 00:00:00 2001 From: Espen Hovlandsdal Date: Tue, 30 Oct 2018 11:42:39 +0100 Subject: [PATCH] fix(gatsby): fix crash on inferring input type with missing node (#9487) If you have a node that references another node with a missing ID, Gatsby currently seems to crash when trying to infer input types: ``` TypeError: Cannot read property 'internal' of null 274 | const linkedNode = findLinkedNode(nodeToFind) 275 | 276 | // Get from cache if found, else store into it > 277 | if (linkedNodeCache[linkedNode.internal.type]) { | ^ 278 | value = linkedNodeCache[linkedNode.internal.type] 279 | } else { 280 | const relatedNodes = getNodes().filter( at internal (packages/gatsby/src/schema/infer-graphql-input-fields.js:277:38) ``` This PR checks if the linked node was actually found, and if not simply returns, skipping the inferring for that field, since we cannot figure out which node type it references. I thought about adding an invariant, but it would need some more context in order to make a meaningful error message. It's also picked up by Gatsby in a different step anyway, with enough context to be helpful: > Error: Invariant Violation: Encountered an error trying to infer a GraphQL type for: "person.favoriteMovie___NODE". There is no corresponding node with the id field matching: "7e997ec9-7eb7-556d-8d80-f0e8c9a321b2" --- .../schema/__tests__/infer-graphql-input-type-test.js | 11 +++++++++++ .../gatsby/src/schema/infer-graphql-input-fields.js | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js b/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js index a76ffe8b7324b..71ce31389b63b 100644 --- a/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js +++ b/packages/gatsby/src/schema/__tests__/infer-graphql-input-type-test.js @@ -985,4 +985,15 @@ describe(`filtering on linked nodes`, () => { expect(getExampleValues({ typeName: `Linked_A` })).toEqual(originalNode) }) + + it(`skips fields with missing nodes`, async () => { + const fields = inferInputObjectStructureFromNodes({ + nodes: [], + exampleValue: { + movie___NODE: `foobar`, + }, + }).inferredFields + + expect(Object.keys(fields)).toHaveLength(0) + }) }) diff --git a/packages/gatsby/src/schema/infer-graphql-input-fields.js b/packages/gatsby/src/schema/infer-graphql-input-fields.js index a7c4c9fb89725..cffcd9d5b639a 100644 --- a/packages/gatsby/src/schema/infer-graphql-input-fields.js +++ b/packages/gatsby/src/schema/infer-graphql-input-fields.js @@ -273,6 +273,13 @@ export function inferInputObjectStructureFromNodes({ const nodeToFind = isArray ? value[0] : value const linkedNode = findLinkedNode(nodeToFind) + // Fall back if the linked node can't be found. Prevents crashing, and is + // picked up in infer-graphql-type.js with an error that gives context to + // the user about which node is missing + if (!linkedNode) { + return + } + // Get from cache if found, else store into it if (linkedNodeCache[linkedNode.internal.type]) { value = linkedNodeCache[linkedNode.internal.type]