{"record":{"id":"a88a0011c747bc40","repo":"Mintplex-Labs/anything-llm","slug":"failed-to-delete-flow","errorCode":null,"errorMessage":"Failed to delete flow","messagePattern":"Failed to delete flow","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"server/endpoints/agentFlows.js","lineNumber":147,"sourceCode":"  //       return response.status(500).json({\n  //         success: false,\n  //         error: error.message,\n  //       });\n  //     }\n  //   }\n  // );\n\n  // Delete a specific flow\n  app.delete(\n    \"/agent-flows/:uuid\",\n    [validatedRequest, flexUserRoleValid([ROLES.admin])],\n    async (request, response) => {\n      try {\n        const { uuid } = request.params;\n        const { success } = AgentFlows.deleteFlow(uuid);\n\n        if (!success) {\n          return response.status(500).json({\n            success: false,\n            error: \"Failed to delete flow\",\n          });\n        }\n\n        return response.status(200).json({\n          success,\n        });\n      } catch (error) {\n        console.error(\"Error deleting flow:\", error);\n        return response.status(500).json({\n          success: false,\n          error: error.message,\n        });\n      }\n    }\n  );\n","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/3aec848f2885144aa8f1e53b9731a04310d5d558/server/endpoints/agentFlows.js#L129-L165","documentation":"DELETE /agent-flows/:uuid maps any deleteFlow failure to this 500. AgentFlows.deleteFlow (server/utils/agentFlows/index.js:155) throws internally when the flow file does not exist or the resolved path escapes the flows dir ('Flow <uuid> not found'), catches it, and returns {success:false} — which the endpoint turns into a 500. So deleting a nonexistent flow yields 500, not 404; fs errors (EACCES/EBUSY) on rmSync produce the same response.","triggerScenarios":"DELETE with a uuid that was already deleted or never existed; double-click on the delete button in the UI firing two requests; uuid with traversal characters; the flow file locked or the storage directory read-only so fs.rmSync fails.","commonSituations":"Stale list in another tab after a delete; concurrent admins; docker bind-mount with wrong ownership making rmSync fail with EACCES.","solutions":["Call GET /agent-flows/list first and only DELETE a uuid that is present (idempotency guard on the client)","Check server console for 'Failed to delete flow:' — it shows whether it was 'not found' vs an fs error like EACCES","If it is an fs error, fix ownership/permissions of storage/plugins/agent-flows (e.g. chown the docker volume) and retry once"],"exampleFix":"// before (server): any deleteFlow failure becomes 500\nconst { success } = AgentFlows.deleteFlow(uuid);\nif (!success) return response.status(500).json({ success:false, error:'Failed to delete flow' });\n\n// after: distinguish not-found from real failures\nconst result = AgentFlows.deleteFlow(uuid);\nif (!result.success && /not found/i.test(result.error || ''))\n  return response.status(404).json({ success:false, error:'Flow not found' });\nif (!result.success)\n  return response.status(500).json({ success:false, error: result.error });","handlingStrategy":"validation","validationCode":"async function safeDeleteFlow(uuid) {\n  const res = await fetch('/api/agent-flows/list');\n  const { flows } = await res.json();\n  if (!flows.some(f => f.uuid === uuid)) return { skipped: true }; // avoids 500 for not-found\n  const del = await fetch(`/api/agent-flows/${encodeURIComponent(uuid)}`, { method:'DELETE' });\n  return { skipped: false, ok: del.ok };\n}","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch(`/api/agent-flows/${uuid}`, { method: 'DELETE' });\n  if (res.status === 500) {\n    const body = await res.json(); // 'Failed to delete flow' may mean already deleted\n    console.warn('delete returned 500:', body.error);\n  }\n} catch (err) {\n  console.error('network failure during delete:', err.message);\n}","preventionTips":["Make delete actions idempotent in the UI: disable the button while a request is in flight","Check membership in the list before deleting to avoid the not-found 500","Ensure the flows directory is writable so rmSync cannot fail with EACCES/EBUSY"],"tags":["agent-flows","http-500","delete","idempotency"],"backgroundTag":"resource-not-found","analyzedSha":"3aec848f2885144aa8f1e53b9731a04310d5d558","analyzedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}