mastra-ai/mastra · error

Source object must be a single RelatedNodeInfo object

Error message

Source object must be a single RelatedNodeInfo object

What it means

The BaseNode.sourceNode getter reads the SOURCE relationship and expects a single RelatedNodeInfo object. If the stored relationship is an array (the shape used for CHILD-style relationships), it throws because a source is by definition one node.

Source

Thrown at packages/rag/src/document/schema/node.ts:33

  protected constructor(init?: BaseNodeParams<T>) {
    const { id_, metadata, relationships } = init || {};
    this.id_ = id_ ?? randomUUID();
    this.metadata = metadata ?? ({} as T);
    this.relationships = relationships ?? {};
  }

  abstract get type(): ObjectType;

  abstract getContent(): string;

  abstract getMetadataStr(): string;

  get sourceNode(): RelatedNodeInfo<T> | undefined {
    const relationship = this.relationships[NodeRelationship.SOURCE];

    if (Array.isArray(relationship)) {
      throw new Error('Source object must be a single RelatedNodeInfo object');
    }

    return relationship;
  }

  get prevNode(): RelatedNodeInfo<T> | undefined {
    const relationship = this.relationships[NodeRelationship.PREVIOUS];

    if (Array.isArray(relationship)) {
      throw new Error('Previous object must be a single RelatedNodeInfo object');
    }

    return relationship;
  }

  get nextNode(): RelatedNodeInfo<T> | undefined {
    const relationship = this.relationships[NodeRelationship.NEXT];

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Assign the SOURCE relationship as a single object: relationships[NodeRelationship.SOURCE] = relatedNodeInfo (not [relatedNodeInfo]).
  2. If data comes from serialized JSON, normalize arrays to a single object before constructing/using the node.
  3. Use library constructors/builders to populate relationships rather than mutating the relationships map directly.

Example fix

// before
node.relationships[NodeRelationship.SOURCE] = [sourceInfo];
// after
node.relationships[NodeRelationship.SOURCE] = sourceInfo;
Defensive patterns

Strategy: type-guard

Validate before calling

const rel = node.relationships[NodeRelationship.SOURCE];
const hasValidSource = rel !== undefined && !Array.isArray(rel);

Type guard

const isSingleRelatedNodeInfo = <T extends NodeRelationship>(v: unknown): v is RelatedNodeInfo<T> =>
  v !== null && typeof v === 'object' && !Array.isArray(v) && 'nodeId' in v;

Try / catch

let source: RelatedNodeInfo | undefined;
try {
  source = node.sourceNode;
} catch (e) {
  if (e instanceof Error && e.message.includes('Source object must be')) {
    const rel = node.relationships[NodeRelationship.SOURCE];
    source = Array.isArray(rel) ? rel[0] : undefined;
  } else throw e;
}

Prevention

When it happens

Trigger: Reading node.sourceNode when node.relationships[NodeRelationship.SOURCE] was manually assigned an array, e.g. relationships: { [NodeRelationship.SOURCE]: [info] }.

Common situations: Hand-building node relationships instead of using node factories, or deserializing/copying relationship maps and wrapping values in arrays uniformly.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/f7007fdc9e529843. Report an issue: GitHub.