{"record":{"id":"82d8c38deeda2972","repo":"FlowiseAI/Flowise","slug":"file-filename-not-found","errorCode":null,"errorMessage":"File ${fileName} not found","messagePattern":"File (.+?) not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/src/storage/GCSStorageProvider.ts","lineNumber":232,"sourceCode":"                if (buffer) {\n                    const file = this.bucket.file(filePath)\n                    await new Promise<void>((resolve, reject) => {\n                        file.createWriteStream()\n                            .on('error', (err) => reject(err))\n                            .on('finish', () => resolve())\n                            .end(buffer)\n                    })\n\n                    // Delete the old file\n                    await fallbackFile.delete()\n\n                    // Check if the directory is empty and delete recursively if needed\n                    await this.cleanEmptyGCSFolders(normalizedChatflowId)\n\n                    return buffer\n                }\n            } catch (fallbackError) {\n                throw new Error(`File ${fileName} not found`)\n            }\n        }\n    }\n\n    async getFilesListFromStorage(...paths: string[]): Promise<FileInfo[]> {\n        const normalizedPaths = paths.map((p) => this.normalizePath(p))\n        const prefix = normalizedPaths.join('/')\n\n        const [files] = await this.bucket.getFiles({ prefix })\n\n        return files.map((file) => ({\n            name: file.name.split('/').pop() || '',\n            path: file.name,\n            size: typeof file.metadata.size === 'string' ? parseInt(file.metadata.size, 10) || 0 : file.metadata.size || 0\n        }))\n    }\n\n    async removeFilesFromStorage(...paths: string[]): Promise<StorageSizeResult> {","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/src/storage/GCSStorageProvider.ts#L214-L250","documentation":"Re-thrown inside the catch block of the GCS file-read fallback path. After the primary object key is not found, the provider tries a legacy key layout (without orgId); if that fallback read also fails, the original/any error is swallowed and replaced with this explicit not-found message.","triggerScenarios":"Requesting a file whose blob does not exist under either the orgId-scoped key or the legacy key layout. The throw is at GCSStorageProvider.ts:231 inside `catch (fallbackError)`.","commonSituations":"The file was deleted or never uploaded; the orgId migration left the blob under a different key; requesting a file immediately after upload before GCS consistency reflects it.","solutions":["Verify the file exists in the bucket with the expected key (orgId/chatflowId/chatId/name and the legacy chatflowId/chatId/name).","Return a 404 to the client and surface only the fileName, not internal key details.","Re-upload or restore the object if it was deleted."],"exampleFix":"// before\nconst buf = await provider.streamStorageFile(chatflowId, chatId, fileName, orgId)\n// after\ntry {\n  const buf = await provider.streamStorageFile(chatflowId, chatId, fileName, orgId)\n} catch (e) {\n  if (/not found/i.test(e.message)) return res.status(404).send('file not found')\n  throw e\n}","handlingStrategy":"try-catch","validationCode":"async function gcsFileExists(bucket: Bucket, key: string): Promise<boolean> {\n  const [exists] = await bucket.file(key).exists()\n  return exists\n}\n// note: existence can change between check and read (TOCTOU); pair with try-catch","typeGuard":"function isNotFound(err: unknown): boolean {\n  return err instanceof Error && /File .* not found/i.test(err.message)\n}","tryCatchPattern":"try {\n  const buf = await provider.streamStorageFile(chatflowId, chatId, fileName, orgId)\n} catch (e) {\n  if (e instanceof Error && /not found/i.test(e.message)) return res.status(404).send('file not found')\n  throw e\n}","preventionTips":["Map not-found errors to 404 at the controller.","Confirm the object key layout (orgId-scoped vs legacy) before serving.","Do not retry indefinitely on a confirmed missing object."],"tags":["gcp","storage","file-not-found"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}