ruvnet/ruflo · error

Cannot add a sibling to an empty conversation

Error message

Cannot add a sibling to an empty conversation

What it means

Thrown by addSibling() in the tree utilities when the conversation has zero messages. Sibling insertion is defined as adding a node next to an existing one under the same parent; with an empty messages array there is no reference node and no parent, so the operation is meaningless — the first message must be created with addChildren instead.

Solutions

  1. Create the first message with addChildren(conv, message) — no siblingId needed.
  2. Guard the regenerate/sibling code path: if conv.messages.length === 0, route to addChildren.
  3. Ensure the user's prompt is persisted before enabling sibling-type actions in the UI.

Example fix

// before
addSibling(conv, message, someId); // throws on empty conv

// after
if (conv.messages.length === 0) {
	addChildren(conv, message);
} else {
	addSibling(conv, message, someId);
}
Defensive patterns

Strategy: validation

Validate before calling

if (conv.messages.length === 0) {
	addChildren(conv, message); // first message becomes the root
} else {
	addSibling(conv, message, siblingId);
}

Type guard

function hasMessages<T>(conv: { messages: T[] }): conv is { messages: [T, ...T[]] } {
	return conv.messages.length > 0;
}

Prevention

When it happens

Trigger: Calling addSibling(conv, message, siblingId) on a fresh/empty conversation (conv.messages.length === 0), typically during initialization code that unconditionally inserts alternatives.

Common situations: Regenerating a response on a brand-new conversation before the prompt was stored; UI wiring the 'edit as new branch' button on an empty thread; tests seeding conversations starting from a sibling insert.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/2365455242df9de9. Report an issue: GitHub.

Appendix: source

Thrown at ruflo/src/ruvocal/src/lib/utils/tree/addSibling.ts:6

import { v4 } from "uuid";
import type { Tree, TreeId, NewNode, TreeNode } from "./tree";

export function addSibling<T>(conv: Tree<T>, message: NewNode<T>, siblingId: TreeId): TreeId {
	if (conv.messages.length === 0) {
		throw new Error("Cannot add a sibling to an empty conversation");
	}
	if (!conv.rootMessageId) {
		throw new Error("Cannot add a sibling to a legacy conversation");
	}

	const sibling = conv.messages.find((m) => m.id === siblingId);

	if (!sibling) {
		throw new Error("The sibling message doesn't exist");
	}

	if (!sibling.ancestors || sibling.ancestors?.length === 0) {
		throw new Error("The sibling message is the root message, therefore we can't add a sibling");
	}

	const messageId = v4();

	conv.messages.push({

View on GitHub (pinned to fa13ee4ad6)