different-ai/openwork · error
Failed to add Workflow (${response.status}).
Error message
Failed to add Workflow (${response.status}). What it means
Thrown by useAttachWorkflowToPlugin in plugin-data.tsx when POSTing a workflow membership to the plugin returns a non-ok response. The body includes configObjectId and membershipSource 'manual'; getRequestError decorates the throw with server payload and status. Indicates the Den API refused to attach the workflow.
Source
Thrown at ee/apps/den-web/app/(den)/dashboard/_components/plugin-data.tsx:817
}
export function useAttachWorkflowToPlugin(pluginId: string) {
const queryClient = useQueryClient();
const { runReauthableAction } = useOrgDashboard();
return useMutation({
mutationFn: async (workflowId: string) => {
await runReauthableAction("attach-workflow-to-plugin", async () => {
const { response, payload } = await requestJson(
`/v1/plugins/${encodeURIComponent(pluginId)}/config-objects`,
{
method: "POST",
body: JSON.stringify({ configObjectId: workflowId, membershipSource: "manual" }),
},
15000,
);
if (!response.ok) {
throw getRequestError(payload, response, `Failed to add Workflow (${response.status}).`);
}
});
return workflowId;
},
onSuccess: async () => {
await Promise.all([
queryClient.invalidateQueries({ queryKey: pluginQueryKeys.detail(pluginId) }),
queryClient.invalidateQueries({ queryKey: pluginQueryKeys.list() }),
queryClient.invalidateQueries({ queryKey: ["me", "library"] }),
]);
},
});
}
View on GitHub (pinned to 2b7df46e8a)
Solutions
- Read the status: 409 -> the workflow is already attached, no action needed; 404 -> refresh workflow list; 403 -> check org role.
- Refresh plugin detail and workflow lists to clear stale ids, then retry.
- Validate the workflowId belongs to the same org before attaching.
- For 5xx, retry once after server health check.
Example fix
// before await attachWorkflow(pluginId, workflowId); // after: skip if already attached const attached = pluginWorkflowIds.includes(workflowId); if (!attached) await attachWorkflow(pluginId, workflowId);
Defensive patterns
Strategy: validation
Validate before calling
const alreadyAttached = plugin.detail?.workflowIds?.includes(workflowId);
if (alreadyAttached) return; // nothing to do, avoids 409
if (!workflowId) throw new Error('Select a workflow before attaching.'); Type guard
function isWorkflowId(v: unknown): v is string {
return typeof v === 'string' && v.length > 0;
} Try / catch
try {
await attachWorkflow(pluginId, workflowId);
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
if (msg.includes('409')) toast('This workflow is already attached.');
else if (msg.includes('404')) { await refreshWorkflows(); toast('Workflow no longer exists.'); }
else toast(msg);
} Prevention
- Check the plugin's current workflow list before attaching to avoid duplicate 409s.
- Invalidate/refresh workflow queries after mutations so ids stay fresh.
- Restrict attach UI to org admins.
- Log the response status server-side to distinguish conflict vs missing.
When it happens
Trigger: POST to the plugin's workflows endpoint with { configObjectId, membershipSource: 'manual' } returns 4xx/5xx: workflow id already attached (409), workflow deleted (404), permission denied (403), or invalid configObjectId format (400).
Common situations: Two tabs attaching the same workflow concurrently; attaching a workflow that another admin removed moments ago; selecting a workflow from a different org due to stale cache.
Related errors
- Failed to archive plugin (${response.status}).
- request_failed
- invalid_payload
- Failed to load desktop policies (${response.status}).
- Desktop policies require an Enterprise plan
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/abc3b3870b1663d1.
Report an issue: GitHub.