Dokploy/dokploy · error · TRPCError
INTERNAL_SERVER_ERROR
INTERNAL_SERVER_ERROR
Error message
Error removing the node
What it means
INTERNAL_SERVER_ERROR wrapper around the cluster node-removal mutation. Any failure in the underlying docker/swarm node removal (node not found, node not drained, Docker API error) is re-thrown with this generic message and the original error as `cause`.
Source
Thrown at apps/dokploy/server/api/routers/cluster.ts:73
const drainCommand = `docker node update --availability drain ${quote([input.nodeId])}`;
const removeCommand = `docker node rm ${quote([input.nodeId])} --force`;
if (input.serverId) {
await execAsyncRemote(input.serverId, drainCommand);
await execAsyncRemote(input.serverId, removeCommand);
} else {
await execAsync(drainCommand);
await execAsync(removeCommand);
}
await audit(ctx, {
action: "delete",
resourceType: "cluster",
resourceId: input.nodeId,
resourceName: input.nodeId,
});
return true;
} catch (error) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: "Error removing the node",
cause: error,
});
}
}),
addWorker: withPermission("server", "create")
.input(
z.object({
serverId: z.string().optional(),
}),
)
.query(async ({ input, ctx }) => {
if (input.serverId) {
const targetServer = await findServerById(input.serverId);
if (targetServer.organizationId !== ctx.session.activeOrganizationId) {
throw new TRPCError({View on GitHub (pinned to 546686ea35)
Solutions
- Inspect `error.cause` for the Docker API message
- Drain the node (`docker node update --availability drain <id>`) before removal
- Verify the target server and its Docker daemon are reachable
- If the node already left, refresh the node list — it may have succeeded despite the error
Example fix
# before docker node rm <nodeId> # fails if active # after docker node update --availability drain <nodeId> docker node rm <nodeId>
Defensive patterns
Strategy: try-catch
Validate before calling
// Drain first via docker API before removing
await docker.getNode(nodeId).update({ Availability: 'drain' }); Try / catch
try {
await trpc.cluster.removeNode.mutate({ nodeId });
} catch (e: any) {
const c = e?.cause?.message ?? '';
if (/not drained/i.test(c)) { /* drain then retry once */ }
else if (/node not found/i.test(c)) { /* refresh list, treat as success */ }
else throw e;
} Prevention
- Always drain swarm nodes before removal
- Check remote Docker connectivity before cluster operations
- Refresh node lists after failures to detect already-removed nodes
When it happens
Trigger: Removing a swarm node that is still active (not drained), a node that already left the swarm, Docker daemon unreachable on the target server, or RPC timeout to the remote Docker socket.
Common situations: Trying to delete a node without draining it first; remote server offline; Docker socket permission issues; race with another operator removing the node simultaneously.
Related errors
AI-assisted analysis of Dokploy/dokploy@546686ea35 (2026-08-27).
Data as JSON: /api/errors/a61788d7325c8569.
Report an issue: GitHub.