ruvnet/ruflo · error · Error
trajectory envelope not found: ${path}
Error message
trajectory envelope not found: ${path} What it means
Thrown synchronously by readSealedTrajectory(path) when existsSync(path) reports the file is absent. The function then would readFile + JSON.parse the envelope, but it guards the missing-file case first with this error. Note it uses existsSync (synchronous) then readFile (async) — a TOCTOU gap means the file could disappear between the two calls, surfacing as a different ENOENT.
Source
Thrown at v3/@claude-flow/browser/src/application/signed-trajectory-service.ts:94
},
key,
{ sealedAt: input.sealedAt },
);
return { envelope, publicKeyHex: key.publicKeyHex };
}
/** Write a signed envelope to disk. */
export async function writeSealedTrajectory(
envelope: SignedTrajectoryEnvelope,
path: string,
): Promise<void> {
await writeFile(resolvePath(path), JSON.stringify(envelope, null, 2), 'utf8');
}
/** Read a signed envelope from disk. */
export async function readSealedTrajectory(path: string): Promise<SignedTrajectoryEnvelope> {
if (!existsSync(path)) throw new Error('trajectory envelope not found: ' + path);
const raw = await readFile(resolvePath(path), 'utf8');
return JSON.parse(raw) as SignedTrajectoryEnvelope;
}
/** Verify a sealed envelope. Thin wrapper that allows trust-list filtering. */
export function verifySealedTrajectory(
envelope: unknown,
options: { trustedPublicKeys?: string[] } = {},
): VerificationResult {
return verifyTrajectory(envelope, options);
}
/**
* Compute the replay plan from a sealed envelope + mutations.
*
* Phase 1 deliberately returns a plan rather than executing — the executor
* needs a live BrowserService and is wired in BrowserService.replayFromEnvelope.
* This keeps the signing/replay logic browser-engine-independent so it can beView on GitHub (pinned to 6b01dc5a68)
Solutions
- Confirm the path was produced by a successful writeSealedTrajectory call in the same process.
- Use an absolute path (resolvePath is applied internally, but absolute removes cwd ambiguity).
- Guard the call with existsSync yourself only when you also control concurrent deletion; otherwise wrap in try/catch and treat absence as 'no trajectory yet'.
- If reading across processes/containers, verify the shared volume mount and that the writer flushed before the reader starts.
Example fix
// before
const env = await readSealedTrajectory(`./runs/${id}`); // throws 61
// after
import { existsSync } from 'node:fs';
import { resolve } from 'node:path';
const p = resolve('./runs', `${id}.json`);
const env = existsSync(p)
? await readSealedTrajectory(p)
: undefined; Defensive patterns
Strategy: validation
Validate before calling
import { existsSync } from 'node:fs';
import { resolve } from 'node:path';
function assertTrajectoryReadable(p) {
const abs = resolve(p);
if (!existsSync(abs)) throw new Error(`no trajectory at ${abs}`);
return abs;
} Type guard
null
Try / catch
try {
const env = await readSealedTrajectory(path);
} catch (e) {
if (e instanceof Error && e.message.startsWith('trajectory envelope not found')) {
return undefined; // treat absence as 'no trajectory yet'
}
throw e;
} Prevention
- Always write with writeSealedTrajectory before reading; assert the write resolved.
- Use absolute paths to avoid cwd-dependent resolution.
- Share a single resolve() helper between writer and reader so paths agree.
When it happens
Trigger: Calling readSealedTrajectory with a path that was never written by writeSealedTrajectory, a relative path resolved against an unexpected cwd, a path on a different filesystem/container, or a path whose write failed silently upstream.
Common situations: Passing a trajectoryId-derived path before sealing; using a relative path that resolves differently in tests vs. runtime; reading from a temp dir cleared between CI steps; mistyping the extension (.json vs none).
Related errors
- Config file already exists: ${targetPath}. Use --force to ov
- Import file not found: ${resolved}
- tuneDistillation: source db not found at ${dbPath}
- frozen human eval set not found (${FROZEN_HUMAN_EVAL_FILE})
- Invalid completion type
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/0c710c4d4f1d256f.
Report an issue: GitHub.