Dokploy/dokploy · error · TRPCError
UNAUTHORIZED
UNAUTHORIZED
Error message
Not authorized to delete this network
What it means
Dokploy's network.remove tRPC mutation throws UNAUTHORIZED when the network being deleted belongs to a different organization than the caller's active session organization. Dokploy is multi-tenant (organizations), so every resource is scoped by organizationId and mutations verify ownership before acting.
Source
Thrown at apps/dokploy/server/api/routers/network.ts:137
message: "Network not found",
});
}
const recreated = await recreateNetwork(input.networkId);
await audit(ctx, {
action: "reload",
resourceType: "network",
resourceId: recreated.networkId,
resourceName: recreated.name,
});
return recreated;
}),
remove: protectedProcedure
.input(apiRemoveNetwork)
.mutation(async ({ ctx, input }) => {
const network = await findNetworkById(input.networkId);
if (network.organizationId !== ctx.session.activeOrganizationId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "Not authorized to delete this network",
});
}
const removed = await removeNetwork(input.networkId);
await audit(ctx, {
action: "delete",
resourceType: "network",
resourceId: removed.networkId,
resourceName: removed.name,
});
return removed;
}),
});
View on GitHub (pinned to 546686ea35)
Solutions
- Switch your active organization (via the org switcher) to the one that owns the network, then retry the delete
- Refresh the networks list so the client holds IDs only for the current organization
- Verify the networkId is correct with network.one/get before calling remove
- If cross-org deletion is legitimately required, have an owner/admin of the owning organization perform it
Example fix
// before
await trpc.network.remove.mutate({ networkId: staleNetworkId });
// after
const nets = await trpc.network.all.query();
const net = nets.find(n => n.networkId === id); // only current-org networks returned
if (net) await trpc.network.remove.mutate({ networkId: net.networkId }); Defensive patterns
Strategy: validation
Validate before calling
const nets = await trpc.network.all.query();
const target = nets.find(n => n.networkId === networkId);
if (!target) throw new Error('Network not in active organization'); Try / catch
try { await trpc.network.remove.mutate({ networkId }); }
catch (e) { if ((e as TRPCError).code === 'UNAUTHORIZED') alert('Switch organization first'); else throw e; } Prevention
- Always resolve resource IDs via a fresh org-scoped list query rather than caching them
- Re-fetch lists after switching active organization
- Pass IDs, not rely on browser-cached state, in automation scripts
When it happens
Trigger: Calling the network.remove mutation (protectedProcedure with apiRemoveNetwork input) with a networkId whose organizationId differs from ctx.session.activeOrganizationId, e.g. a user switching organizations in the UI but using a stale networkId copied from another org.
Common situations: Stale networkId cached in the client after switching active organization in Dokploy; scripts/automation reusing IDs across instances; UI list not refreshed after org change.
Related errors
AI-assisted analysis of Dokploy/dokploy@546686ea35 (2026-08-27).
Data as JSON: /api/errors/05350deca2a5c24b.
Report an issue: GitHub.