{"record":{"id":"d9558727e61bbdaf","repo":"different-ai/openwork","slug":"failed-to-archive-plugin-response-status","errorCode":null,"errorMessage":"Failed to archive plugin (${response.status}).","messagePattern":"Failed to archive plugin \\((.+?)\\)\\.","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/dashboard/_components/plugin-data.tsx","lineNumber":789,"sourceCode":"      queryClient.invalidateQueries({ queryKey: pluginQueryKeys.list() });\n    },\n  });\n}\n\nexport function useArchivePlugin() {\n  const queryClient = useQueryClient();\n  const { runReauthableAction } = useOrgDashboard();\n\n  return useMutation({\n    mutationFn: async (pluginId: string) => {\n      await runReauthableAction(\"archive-plugin\", async () => {\n        const { response, payload } = await requestJson(\n          `/v1/plugins/${encodeURIComponent(pluginId)}/archive`,\n          { method: \"POST\" },\n          15000,\n        );\n        if (!response.ok) {\n          throw getRequestError(payload, response, `Failed to archive plugin (${response.status}).`);\n        }\n      });\n      return pluginId;\n    },\n    onSuccess: (pluginId) => {\n      queryClient.removeQueries({ queryKey: pluginQueryKeys.detail(pluginId) });\n      queryClient.invalidateQueries({ queryKey: pluginQueryKeys.list() });\n    },\n  });\n}\n\nexport function useAttachWorkflowToPlugin(pluginId: string) {\n  const queryClient = useQueryClient();\n  const { runReauthableAction } = useOrgDashboard();\n\n  return useMutation({\n    mutationFn: async (workflowId: string) => {\n      await runReauthableAction(\"attach-workflow-to-plugin\", async () => {","sourceCodeStart":771,"sourceCodeEnd":807,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_components/plugin-data.tsx#L771-L807","documentation":"Thrown by useArchivePlugin in plugin-data.tsx when the POST to /v1/plugins/:id/archive returns a non-ok HTTP status. getRequestError attaches the server payload and status to the thrown error so the UI toast surfaces the real cause. It means the Den API rejected the archive request, not a client-side bug.","triggerScenarios":"POST /v1/plugins/{pluginId}/archive responds 4xx/5xx: plugin id not found (404), caller lacks org-admin permission (403), session expired (401), or server error (5xx). 15s timeout exceeded also surfaces as failure.","commonSituations":"Archiving a plugin that was already deleted by a teammate; stale dashboard data after role downgrade; Den server restart/maintenance window; expired Better-Auth session token.","solutions":["Check the HTTP status embedded in the error message and the server payload for the real reason (401 -> re-authenticate, 403 -> confirm org role, 404 -> refresh plugin list).","Refresh the dashboard so the plugin list is not stale before retrying the archive.","If 5xx or timeout, retry after confirming the Den server is healthy (server logs, uptime).","Verify the logged-in account still has plugin management permissions on the org."],"exampleFix":"// before: retrying archive on a stale id\nawait archivePlugin(pluginId);\n// after: confirm the plugin still exists server-side first\nconst detail = await fetchPluginDetail(pluginId);\nif (detail) await archivePlugin(pluginId);","handlingStrategy":"try-catch","validationCode":"if (!pluginId || typeof pluginId !== 'string') throw new Error('pluginId is required before archiving.');","typeGuard":"function isPluginId(v: unknown): v is string {\n  return typeof v === 'string' && v.length > 0;\n}","tryCatchPattern":"try {\n  await archivePlugin(pluginId);\n} catch (e) {\n  const msg = e instanceof Error ? e.message : String(e);\n  if (msg.includes('401')) promptReSignIn();\n  else if (msg.includes('403')) toast('You need org admin permission to archive plugins.');\n  else if (msg.includes('404')) { await refreshPluginList(); toast('Plugin no longer exists.'); }\n  else toast(msg);\n}","preventionTips":["Refresh the plugin list before destructive mutations in long-lived tabs.","Keep sessions alive / re-authenticate before admin operations.","Surface the interpolated HTTP status from the error message in UI toasts for faster diagnosis.","Gate archive UI on the user's org role so non-admins never reach the call."],"tags":["http","api","permissions","plugin-management"],"backgroundTag":"http-non-ok-response","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}