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

  1. Switch your active organization (via the org switcher) to the one that owns the network, then retry the delete
  2. Refresh the networks list so the client holds IDs only for the current organization
  3. Verify the networkId is correct with network.one/get before calling remove
  4. 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

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.