ruvnet/ruflo · error · Error

File not found

Error message

File not found

What it means

In the rvf (file-backed/in-memory) storage backend, openDownloadStream(id).toArray() looks up the base64 blob in an in-memory files Map (rvf.ts:1056) and throws "File not found" on a miss. The Map is hydrated from the on-disk store (./db JSON persistence) at startup, so a miss means the id was never persisted in this store or the persisted data is gone.

Solutions

  1. Confirm which store the file was written to (check the db JSON file's files keys) and read from the same backend
  2. Return a friendly 404 from the download path when the blob is gone, and clean the dangling message reference
  3. Pin the store location with an absolute DATA_DIR so restarts from any cwd see the same data
  4. Re-upload or restore the store file from backup

Example fix

// before
const [buf] = await collections.bucket.openDownloadStream(fileId).toArray(); // throws: File not found

// after
const existing = await collections.bucket.find({ _id: fileId }).toArray();
if (existing.length === 0) throw error(404, "File no longer available");
const [buf] = await collections.bucket.openDownloadStream(fileId).toArray();
Defensive patterns

Strategy: try-catch

Validate before calling

const existing = await collections.bucket.find({ _id: fileId }).toArray();
if (existing.length === 0) throw error(404, "File no longer available");

Type guard

null

Try / catch

try {
	const [buf] = await collections.bucket.openDownloadStream(fileId).toArray();
} catch (e) {
	if (e instanceof Error && e.message === "File not found") throw error(404, "File expired");
	throw e;
}

Prevention

When it happens

Trigger: Awaiting bucket.openDownloadStream(fileId).toArray() when the rvf store's files Map has no entry for the id: server restarted with a missing/empty store file, DATA_DIR/working directory changed between runs (scheduleSave writes relative paths), conversations imported from another backend, or the file was deleted via bucket.delete().

Common situations: Dev server run from a different cwd so ./db resolves elsewhere; wiping the db folder but keeping conversation records; switching MONGODB_URL on/off so uploads landed in one backend and reads hit another; concurrent saves losing a just-uploaded file after a crash.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at ruflo/src/ruvocal/src/lib/server/database/rvf.ts:1056

					filename,
					contentType: options?.contentType ?? "application/octet-stream",
					length: data.length,
					data,
					metadata: options?.metadata ?? {},
					createdAt: new Date(),
				});
				scheduleSave();
			},
		};
	}

	openDownloadStream(id: ObjectId | string) {
		const fileId = typeof id === "string" ? id : id.toString();
		const files = this.files;
		return {
			async toArray(): Promise<Buffer[]> {
				const file = files.get(fileId);
				if (!file) throw new Error("File not found");
				return [Buffer.from(file.data as string, "base64")];
			},
		};
	}

	async delete(id: ObjectId | string) {
		const fileId = typeof id === "string" ? id : id.toString();
		this.files.delete(fileId);
		scheduleSave();
	}

	async find(filter: Record<string, unknown> = {}) {
		const results: Record<string, unknown>[] = [];
		for (const doc of this.files.values()) {
			if (matchesFilter(doc, filter)) {
				const { data, ...meta } = doc;
				results.push(meta);
			}

View on GitHub (pinned to fa13ee4ad6)