ruvnet/ruflo · error
Cannot add a sibling to a legacy conversation
Error message
Cannot add a sibling to a legacy conversation
What it means
Thrown by addSibling() when the conversation has messages but no rootMessageId — a legacy, pre-tree conversation. Sibling insertion requires re-hanging the new node under the sibling's parent using ancestor chains, which legacy conversations do not store, so the operation is unsupported on them.
Solutions
- On legacy conversations, offer append-only flows (addChildren to the last message) instead of branching.
- Migrate the conversation to the tree format (assign rootMessageId and ancestors per node) to unlock sibling operations.
- Detect legacy format early in the UI (no rootMessageId) and disable branch affordances.
Example fix
// before
addSibling(conv, message, siblingId); // throws on legacy conv
// after
if (!conv.rootMessageId) {
addChildren(conv, message, conv.messages[conv.messages.length - 1].id);
} else {
addSibling(conv, message, siblingId);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!conv.rootMessageId) {
throw new Error("branching unsupported on legacy conversation");
}
addSibling(conv, message, siblingId); Type guard
function isTreeConversation(conv: { rootMessageId?: string }): conv is { rootMessageId: string } {
return typeof conv.rootMessageId === "string" && conv.rootMessageId.length > 0;
} Prevention
- Migrate legacy conversations on read: assign rootMessageId and ancestors before use.
- Feature-flag branch UI off for legacy data.
- Version your persisted conversation schema so format checks are explicit.
When it happens
Trigger: addSibling(conv, message, siblingId) where conv.rootMessageId is undefined — any alternative/branch action attempted on old-format data.
Common situations: Users reopening very old conversations and clicking 'edit message as new alternative'; bulk-replaying branching operations over imported legacy history.
Related errors
- This is a legacy conversation, you can only append to the…
- Cannot add a sibling to an empty conversation
- Message not found
- The sibling message doesn't exist
- The sibling message is the root message, therefore we can't…
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/6844f3fe497b6bbd.
Report an issue: GitHub.
Appendix: source
Thrown at ruflo/src/ruvocal/src/lib/utils/tree/addSibling.ts:9
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({
...message,
id: messageId,
ancestors: sibling.ancestors,View on GitHub (pinned to fa13ee4ad6)