name: rfdb-metadata-gotchas description: | Fix silent metadata issues in RFDB node storage. Covers two traps: (1) metadata flattening — nested metadata fields become top-level after serialization, so node.metadata.field is undefined but node.field works. (2) reserved keys — fields named "type", "id", "name", "file", "exported" are silently stripped from metadata by _parseNode() to prevent overwriting top-level node fields. author: Claude Code version: 2.0.0 date: 2026-05-03
RFDB Metadata Gotchas
Trap 1: Metadata Flattening
RFDB serialization flattens nested metadata to the node's top level.
What happens:
- Analyzer stores:
{id, type, file, metadata: {handlerStart: 93}} client.addNodesserializes metadata as JSON string_parseNodedeserializes and spreads onto top level- After retrieval:
handlerStartis at TOP LEVEL, not nested
Wrong:
const handlerStart = route.metadata?.handlerStart; // undefined!
Correct:
const handlerStart = route.handlerStart; // 93
TypeScript interfaces — define custom fields at top level:
interface HttpRouteNode extends BaseNodeRecord {
type: 'http:route';
handlerStart?: number; // top level, not nested under metadata
}
Trap 2: Reserved Keys (Silent Data Loss)
_parseNode() strips these keys from metadata to prevent overwriting top-level node fields:
| Key | Why reserved |
|---|---|
type |
Would overwrite node type (VARIABLE, FUNCTION, etc.) |
id |
Would overwrite semantic ID |
name |
Would overwrite display name |
file |
Would overwrite file path |
exported |
Would overwrite export flag |
nodeType |
Internal RFDB wire field |
originalId |
Internal legacy field |
semanticId |
Internal field |
Use non-colliding names:
| Don't use | Use instead |
|---|---|
metadata.type |
metadata.tsType |
metadata.name |
metadata.displayName |
metadata.id |
metadata.externalId |
Detection
console.log(JSON.stringify(node, null, 2))— check if field is at top level- Raw wire format:
backend._client.getAllNodes()returnsWireNodewith metadata as JSON string - If field appears in raw wire but not in parsed node → reserved key stripping
Notes
- Applies to ALL custom fields on nodes, not just metadata
- Both TestDatabaseBackend and RFDBServerBackend have this behavior
- If you need truly nested data, store it as a JSON string that doesn't get auto-parsed