gatsbyjs/gatsby · critical
The `id` parameter passed to createNodeId must be a String o
Error message
The `id` parameter passed to createNodeId must be a String or Number (got ${typeof id}) What it means
createNodeId generates deterministic UUIDs from an input id and a namespace. The id parameter must be a string or number (numbers are coerced to strings). If it is any other type (object, undefined, null, boolean, array), Gatsby panics because the UUID generation cannot produce a deterministic hash.
Source
Thrown at packages/gatsby/src/utils/create-node-id.ts:40
* - The conversion needs to be fast
* - The result should be predictably short as it may be used in urls
*
* High level this step is meant to prevent people from using our `id` to have meaning in their site and it's meant
* to make sure the id ends up being short, whatever the input size was.
*
* Note: UUID is relatively slow because it calls into the native crypto library to generate SHA-1 hashes.
* We do need the low collision rate of SHA-1 so we use a local (global) cache to speed up repetitive calls
*
* @param {String | Number} id - A string of arbitrary length
* @param {String} namespace - Namespace to use for UUID
*
* @return {String} - UUID
*/
export function createNodeId(id: string | number, namespace: string): string {
if (typeof id === `number`) {
id = id.toString()
} else if (typeof id !== `string`) {
report.panic(
`The \`id\` parameter passed to createNodeId must be a String or Number (got ${typeof id})`
)
} else if (typeof namespace !== `string`) {
report.panic(
`The \`namespace\` parameter passed to createNodeId must be a String (got ${typeof namespace})`
)
}
let nsHash = unprefixedCache.get(namespace)
if (!nsHash) {
nsHash = uuidv5(namespace, seedConstant) as string
unprefixedCache.set(namespace, nsHash)
}
// Calling uuid is relatively expensive because it calls into crypto for sha1.
// We use a local map to cache calls with the same ns+id pair, which helps a lot.
let nsCache = namespacedCache.get(namespace)
if (!nsCache) {View on GitHub (pinned to 8b06340921)
Solutions
- Ensure the first argument to createNodeId is always a string or number -- check the data source for null/undefined keys.
- Add a guard: createNodeId(String(record.id || record.slug || fallback), 'namespace').
- Log the value before calling createNodeId to identify which record produces the bad id.
- Fix upstream data fetching to always provide a valid identifier.
Example fix
// before
const nodeId = createNodeId(data.maybeId, 'my-plugin')
// after
if (!data.id) {
reporter.warn(`Record missing id: ${JSON.stringify(data)}`)
return
}
const nodeId = createNodeId(data.id, 'my-plugin') Defensive patterns
Strategy: validation
Validate before calling
// Validate id before calling createNodeId
function validateCreateNodeIdInput(id) {
if (typeof id !== 'string' && typeof id !== 'number') {
throw new Error('createNodeId requires string or number, got ' + typeof id)
}
}
validateCreateNodeIdInput(record.id) Type guard
// Type guard for valid createNodeId id parameter
function isValidNodeId(id) {
return typeof id === 'string' || typeof id === 'number'
}
if (!isValidNodeId(record.id)) {
reporter.warn('Skipping node: invalid id type ' + typeof record.id)
return
}
var nodeId = createNodeId(record.id, 'my-plugin') Prevention
- Always validate that the id from upstream data is a string or number before calling createNodeId.
- Filter or skip records with missing/null primary keys.
- Log records that fail validation to identify data quality issues.
When it happens
Trigger: Calling createNodeId(undefined, 'namespace') or createNodeId({ id: 1 }, 'namespace') -- passing a non-string/non-number first argument. Typically inside sourceNodes, onCreateNode, or a source plugin where the id comes from upstream data that is unexpectedly undefined or an object.
Common situations: A source plugin fetches data where a record's primary key is null or missing, and that field is passed to createNodeId. A gatsby-node.js bug where a variable used as id is undefined due to a typo or missing data path. Passing an object instead of object.id.
Related errors
- The `namespace` parameter passed to createNodeId must be a S
- RemoteFileNode does not have a mimeType. The field is requir
- createNodeId must be a function, was ${typeof createNodeId}
- createNodeId must be a function, was ${typeof createNodeId}
- The node internal.owner field is set automatically by Gatsby
AI-assisted analysis of gatsbyjs/gatsby@8b06340921 (2026-08-13).
Data as JSON: /api/errors/a1d8e6e3791eae35.
Report an issue: GitHub.