can1357/oh-my-pi · error · Error

Entry ${leafId} not found

Error message

Entry ${leafId} not found

What it means

SessionManager.createBranchedSession(leafId) extracts the root-to-leaf path into a new session file. It derives the path via getBranch(leafId); when that returns an empty array — which happens when leafId does not resolve to any entry in the session tree — it throws this Error instead of silently producing an empty session.

Source

Thrown at packages/coding-agent/src/session/session-manager.ts:2679

			parentId: branchFromId,
			timestamp: nowIso(),
			fromId: branchFromId ?? "root",
			summary,
			details,
			fromExtension,
		};
		this.#recordEntry(entry);
		return entry.id;
	}

	/**
	 * Create a new session file containing only the path from root to `leafId`.
	 * Returns the new file path, or undefined when not persisting.
	 */
	createBranchedSession(leafId: string): string | undefined {
		const sourceSessionFile = this.#sessionFile;
		const branchPath = this.getBranch(leafId);
		if (branchPath.length === 0) throw new Error(`Entry ${leafId} not found`);

		// Drop label entries from the path; recreate them fresh from the resolved map.
		const entriesToKeep = branchPath.filter(entry => entry.type !== "label");
		const keptIds = new Set(entriesToKeep.map(entry => entry.id));
		const labelsToCarry: Array<{ targetId: string; label: string }> = [];
		for (const [targetId, label] of this.#index.labelsInEffect()) {
			if (keptIds.has(targetId)) labelsToCarry.push({ targetId, label });
		}

		const timestamp = nowIso();
		const newSessionId = mintSessionId();
		this.#reconcileSessionDirForFallback();
		const newSessionFile = path.join(this.#sessionDir, `${fileSafeTimestamp(timestamp)}_${newSessionId}.jsonl`);
		const header: SessionHeader = {
			type: "session",
			version: CURRENT_SESSION_VERSION,
			id: newSessionId,
			timestamp,

View on GitHub (pinned to 9690622007)

Solutions

  1. Fetch the current leaf id from the session (e.g. the last entry of the active branch) and pass that instead of a cached id.
  2. Confirm the id is an entry id of this same session file; re-read the entries and search for it.
  3. If the intended leaf was pruned, undo the pruning or pick a surviving ancestor entry on the same path.
  4. Wrap in try-catch and surface 'session entry not found' to the user, offering to fork from the current tip.

Example fix

// before
session.createBranchedSession(cachedLeafId);
// after
const entries = session.getBranch(session.currentLeafId ?? undefined);
const target = entries.find(e => e.id === leafId);
const newFile = target ? session.createBranchedSession(target.id) : session.createBranchedSession(session.currentLeafId);
Defensive patterns

Strategy: validation

Validate before calling

const leafExists = session.getEntries().some(e => e.id === leafId);
if (!leafExists) throw new Error(`createBranchedSession: ${leafId} not in session`);
const newPath = session.createBranchedSession(leafId);

Try / catch

try {
  return session.createBranchedSession(leafId);
} catch (err) {
  if (err.message.includes("not found")) {
    logger.warn(`Leaf ${leafId} gone; forking from current tip`);
    return session.createBranchedSession(session.currentLeafId);
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling createBranchedSession with an id absent from the session index, an id from another session file, or after the targeted entry was removed by earlier branch/prune operations so getBranch can no longer reconstruct a path.

Common situations: Persisting a forked conversation after the UI held a stale leaf id across a session reload; exporting a subtree using an id captured before the tree was modified; consumers confusing message ids with entry ids.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/ed83e3e89126111b. Report an issue: GitHub.