{"record":{"id":"7e2b2c9f0e546468","repo":"ruvnet/ruflo","slug":"file-not-found-7e2b2c","errorCode":null,"errorMessage":"File not found","messagePattern":"File not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ruflo/src/ruvocal/src/lib/server/database/rvf.ts","lineNumber":1056,"sourceCode":"\t\t\t\t\tfilename,\n\t\t\t\t\tcontentType: options?.contentType ?? \"application/octet-stream\",\n\t\t\t\t\tlength: data.length,\n\t\t\t\t\tdata,\n\t\t\t\t\tmetadata: options?.metadata ?? {},\n\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t});\n\t\t\t\tscheduleSave();\n\t\t\t},\n\t\t};\n\t}\n\n\topenDownloadStream(id: ObjectId | string) {\n\t\tconst fileId = typeof id === \"string\" ? id : id.toString();\n\t\tconst files = this.files;\n\t\treturn {\n\t\t\tasync toArray(): Promise<Buffer[]> {\n\t\t\t\tconst file = files.get(fileId);\n\t\t\t\tif (!file) throw new Error(\"File not found\");\n\t\t\t\treturn [Buffer.from(file.data as string, \"base64\")];\n\t\t\t},\n\t\t};\n\t}\n\n\tasync delete(id: ObjectId | string) {\n\t\tconst fileId = typeof id === \"string\" ? id : id.toString();\n\t\tthis.files.delete(fileId);\n\t\tscheduleSave();\n\t}\n\n\tasync find(filter: Record<string, unknown> = {}) {\n\t\tconst results: Record<string, unknown>[] = [];\n\t\tfor (const doc of this.files.values()) {\n\t\t\tif (matchesFilter(doc, filter)) {\n\t\t\t\tconst { data, ...meta } = doc;\n\t\t\t\tresults.push(meta);\n\t\t\t}","sourceCodeStart":1038,"sourceCodeEnd":1074,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/ruflo/src/ruvocal/src/lib/server/database/rvf.ts#L1038-L1074","documentation":"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().","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst stream = bucket.openDownloadStream(id);\nconst buf = (await stream.toArray())[0]; // throws if missing\n\n// after\nconst file = bucket.files.get(String(id));\nif (!file) return res404('file not found');\nconst buf = Buffer.from(file.data, 'base64');","handlingStrategy":"try-catch","validationCode":"function hasInMemoryFile(bucket: { files: Map<string, unknown> }, id: string): boolean { return bucket.files.has(String(id)); }","typeGuard":"function isInMemoryFilePresent(files: Map<string, unknown>, id: string): boolean { return files.has(String(id)); }","tryCatchPattern":"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; }","preventionTips":["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."],"tags":["database","file-storage","in-memory","ruvocal"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}