ruvnet/ruflo · error · Error

File not found

Error message

File not found

What it means

The in-memory (RVF) storage adapter's counterpart to error 15: openDownloadStream().toArray() looks up files.get(fileId) on an in-memory Map and throws when the id is absent. This adapter is the auto-fallback when MONGODB_URL is not set; data is persisted to ./db by scheduleSave().

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 6b01dc5a68)

Solutions

  1. Point all instances at the same persisted store (set MONGODB_URL or share the ./db volume) so file state is consistent.
  2. Confirm scheduleSave flushed before process exit (the in-memory store is only durable to disk on save).
  3. Pin requests to the instance that owns the file, or use the Postgres/Mongo adapter for multi-instance deployments.
  4. Re-upload the file against the current instance.

Example fix

// before
const stream = bucket.openDownloadStream(id);
const buf = (await stream.toArray())[0]; // throws if missing

// after
const file = bucket.files.get(String(id));
if (!file) return res404('file not found');
const buf = Buffer.from(file.data, 'base64');
Defensive patterns

Strategy: try-catch

Validate before calling

function hasInMemoryFile(bucket: { files: Map<string, unknown> }, id: string): boolean { return bucket.files.has(String(id)); }

Type guard

function isInMemoryFilePresent(files: Map<string, unknown>, id: string): boolean { return files.has(String(id)); }

Try / catch

try { return await bucket.openDownloadStream(id).toArray(); } catch (e) { if ((e as Error).message === 'File not found') return res.status(404).json({ error: 'file not found' }); throw e; }

Prevention

When it happens

Trigger: Downloading a file id not present in the in-memory files Map: a fresh process where the persisted ./db file has not been loaded or was deleted; an id from a different process/instance (in-memory stores are not shared); a file that was never written or was evicted.

Common situations: Running multiple instances without shared storage (each has its own in-memory Map); the ./db persistence file was cleared or not mounted in a container restart; an upload targeted a different instance than the download; dev restart lost unsaved data because scheduleSave was deferred.

Related errors


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