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
- Point all instances at the same persisted store (set MONGODB_URL or share the ./db volume) so file state is consistent.
- Confirm scheduleSave flushed before process exit (the in-memory store is only durable to disk on save).
- Pin requests to the instance that owns the file, or use the Postgres/Mongo adapter for multi-instance deployments.
- 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
- Use shared durable storage (Mongo/Postgres) for multi-instance deployments.
- Ensure scheduleSave flushes before exit so the ./db file is current.
- Pin upload+download to the same instance for the in-memory adapter.
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
- File not found
- User not found
- SSRF guard: invalid URL — ${rawUrl}
- SSRF guard: only HTTPS URLs are permitted, got ${parsed.prot
- SSRF guard: private/loopback host rejected — ${host}
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/7e2b2c9f0e546468.
Report an issue: GitHub.