{"record":{"id":"4dca0c508580445f","repo":"gatsbyjs/gatsby","slug":"could-not-create-more-nodes-maximum-node-count-is","errorCode":null,"errorMessage":"Could not create more nodes. Maximum node count is reached: ${lastNodeCounter}","messagePattern":"Could not create more nodes\\. Maximum node count is reached: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/gatsby/src/redux/actions/public.js","lineNumber":588,"sourceCode":"  // It's possible the file node was never created as sometimes tools will\n  // write and then immediately delete temporary files to the file system.\n  const deleteDescendantsActions =\n    internalNode &&\n    findChildren(internalNode.children).map(getNode).map(createDeleteAction)\n\n  if (deleteDescendantsActions && deleteDescendantsActions.length) {\n    return [...deleteDescendantsActions, deleteAction]\n  } else {\n    return deleteAction\n  }\n}\n\n// We add a counter to node.internal for fast comparisons/intersections\n// of various node slices. The counter must increase even across builds.\nfunction getNextNodeCounter() {\n  const lastNodeCounter = store.getState().status.LAST_NODE_COUNTER ?? 0\n  if (lastNodeCounter >= Number.MAX_SAFE_INTEGER) {\n    throw new Error(\n      `Could not create more nodes. Maximum node count is reached: ${lastNodeCounter}`\n    )\n  }\n  return lastNodeCounter + 1\n}\n\n// memberof notation is added so this code can be referenced instead of the wrapper.\n/**\n * Create a new node.\n * @memberof actions\n * @param {Object} node a node object\n * @param {string} node.id The node's ID. Must be globally unique.\n * @param {string} node.parent The ID of the parent's node. If the node is\n * derived from another node, set that node as the parent. Otherwise it can\n * just be `null`.\n * @param {Array} node.children An array of children node IDs. If you're\n * creating the children nodes while creating the parent node, add the\n * children node IDs here directly. If you're adding a child node to a","sourceCodeStart":570,"sourceCodeEnd":606,"githubUrl":"https://github.com/gatsbyjs/gatsby/blob/8b06340921ffdf23125a365b9c9923690cb62ce6/packages/gatsby/src/redux/actions/public.js#L570-L606","documentation":"Gatsby assigns each node a monotonically increasing integer counter (stored in redux state.status.LAST_NODE_COUNTER) for fast comparisons/intersections of node slices. getNextNodeCounter() throws when this counter has already reached Number.MAX_SAFE_INTEGER (2^53 - 1), since no further unique counter value can be safely represented. This is a hard internal ceiling on the total number of nodes ever created, even across builds (the counter persists). Hitting it implies an astronomically large node volume or a runaway generator that never stops emitting nodes.","triggerScenarios":"Invoked implicitly inside createNode()/createNodeField paths every time a node is created and sanitizeNode assigns it an internal.counter. The throw fires only when store.getState().status.LAST_NODE_COUNTER >= 9007199254740991 at the moment of increment.","commonSituations":"A source plugin stuck in an infinite loop creating nodes (e.g. pagination/paging bug generating millions of duplicate nodes), or importing a massive dataset whose items each fan out into many child nodes across repeated builds (counter never resets, even after DELETE_CACHE only resets some state). Practically unreachable except via buggy generation logic.","solutions":["Audit source/transformer plugins for runaway node generation: log node count per plugin and cap loops/pagination.","Ensure createNode is not being called inside a recursive/unbounded loop or re-emitting the same nodes with new IDs each build.","If legitimately creating a huge node volume, deduplicate by stable content digest and reuse existing node IDs instead of minting new ones.","As a last resort, clear persisted redux state (.cache/redux state, LAST_NODE_COUNTER) and rebuild from a clean source."],"exampleFix":"// before\nfor (const item of items) {\n  for (const variant of item.variants) {\n    createNode({ id: `${item.id}-${variant.id}-${Date.now()}`, ... }) // unbounded, ever-growing\n  }\n}\n// after - stable IDs, deduped, no unbounded growth\nfor (const item of items) {\n  createNode({ id: `item-${item.id}`, parent: null, ... })\n}","handlingStrategy":"validation","validationCode":"// Before bulk-creating nodes, estimate count and cap generation.\nconst MAX = Number.MAX_SAFE_INTEGER // informational only\nconst planned = items.reduce((n, i) => n + i.variants.length, 0)\nif (planned > 5_000_000) {\n  throw new Error(`Refusing to generate ${planned} nodes; possible runaway source`)\n}\n// Prefer stable IDs + content-digest dedupe so re-runs do not grow the counter.\n","typeGuard":"// Guard against passing an object whose generation would be unbounded.\nfunction isBoundedNodeSource(items) {\n  return Array.isArray(items) && items.length > 0 && items.every(i =>\n    i && typeof i.id === 'string' && Array.isArray(i.variants)\n  )\n}","tryCatchPattern":null,"preventionTips":["Always derive node ids from stable content digests so duplicate sources do not mint new nodes.","Log per-plugin node counts in onPluginLifecycle and set a soft ceiling alert.","Never call createNode inside an unbounded while/for loop without a known termination bound.","Periodically run gatsby clean if you suspect the persisted counter has drifted."],"tags":["redux","nodes","internal-limit","state"],"backgroundTag":null,"analyzedSha":"8b06340921ffdf23125a365b9c9923690cb62ce6","analyzedAt":"2026-08-13T02:36:21.405Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}