Debugging Missing or Stale Data Fields on Nodes
Overview of LMDB
datastore behavior changes
In Gatsby 3 we introduced a new data store called LMDB
. In Gatsby 4 it became the default data store. It allows Gatsby to execute data layer related processing outside of the main build process and enables Gatsby to run queries in multiple processes as well as support additional rendering strategies (DSG and SSR).
In a lot of cases that change is completely invisible to users, but there are cases where things behave differently.
Direct node mutations in various API lifecycles are not persisted anymore. In previous Gatsby versions it did work because source of truth for the data layer was directly in Node.js memory, so mutating node was in fact mutating source of truth. Now Gatsby edits data it receives from the database, so unless it explicitly upserts data to this database after edits, those edits will not be persisted (even for same the same build).
Common errors when doing swap to LMDB
will be that some fields don’t exist anymore or are null
/undefined
when trying to execute GraphQL queries.
Diagnostic mode
Gatsby (starting with version 4.4) can detect those node mutations. Unfortunately it adds measurable overhead so it isn’t enabled by default. You can opt into it when you see data related issues (particularly when you didn’t have this issue before using LMDB
). To enable diagnostic mode:
- Use truthy environment variable
GATSBY_DETECT_NODE_MUTATIONS
: - Or use
DETECT_NODE_MUTATIONS
config flag:
Example diagnostic message you might see:
It will point you to the code that is trying to mutate nodes. Note that it might also point to installed plugins in which case you should notify the plugin maintainer about it.
Please Note: Be sure to stop using this mode once you find and handle all problematic code paths as it will decrease performance.
Migration
Mutating a node in onCreateNode
Instead of mutating nodes directly, createNodeField
action should be used instead. This way Gatsby will update the source of truth (to actually update the node in the datastore). createNodeField
will create that additional field under fields.fieldName
. If you want to preserve schema shape, so that additional field is on the root of a node, you can use schema customization.