Dokploy/dokploy · error · TRPCError

UNAUTHORIZED

UNAUTHORIZED

Error message

You are not authorized to access this server

What it means

Access-control check in the swarm 'nodes' query: when a serverId is supplied, the server row is looked up and its organizationId must equal the caller session's activeOrganizationId. Otherwise UNAUTHORIZED is thrown before getSwarmNodes runs. This prevents querying Docker swarm nodes on a server belonging to a different organization.

Source

Thrown at apps/dokploy/server/api/routers/swarm.ts:25

	getSwarmNodes,
} from "@dokploy/server";
import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { createTRPCRouter, withPermission } from "../trpc";
import { containerIdRegex } from "./docker";

export const swarmRouter = createTRPCRouter({
	getNodes: withPermission("docker", "read")
		.input(
			z.object({
				serverId: z.string().optional(),
			}),
		)
		.query(async ({ input, ctx }) => {
			if (input.serverId) {
				const server = await findServerById(input.serverId);
				if (server.organizationId !== ctx.session?.activeOrganizationId) {
					throw new TRPCError({
						code: "UNAUTHORIZED",
						message: "You are not authorized to access this server",
					});
				}
			}
			return await getSwarmNodes(input.serverId);
		}),
	getNodeInfo: withPermission("docker", "read")
		.input(z.object({ nodeId: z.string(), serverId: z.string().optional() }))
		.query(async ({ input, ctx }) => {
			if (input.serverId) {
				const server = await findServerById(input.serverId);
				if (server.organizationId !== ctx.session?.activeOrganizationId) {
					throw new TRPCError({
						code: "UNAUTHORIZED",
						message: "You are not authorized to access this server",
					});
				}

View on GitHub (pinned to 546686ea35)

Solutions

  1. Switch the active organization in the UI to the one that owns the server, then retry
  2. Verify the serverId belongs to your current organization (check the servers list for that org)
  3. If the session org data is stale, log out and back in / refresh the session

Example fix

// before
const nodes = await api.swarm.nodes({ serverId });
// after
const server = await api.server.byId(serverId); // 404s if other-org/invisible
const nodes = await api.swarm.nodes({ serverId });
// better: omit serverId to target the current org's default server
Defensive patterns

Strategy: validation

Validate before calling

const servers = await api.server.all(); // org-scoped
if (servers.some(s => s.serverId === serverId)) {
  const nodes = await api.swarm.nodes({ serverId });
}

Type guard

const serverInActiveOrg = (
  servers: { serverId: string }[], id: string
) => servers.some(s => s.serverId === id);

Try / catch

try { await api.swarm.nodes({ serverId }); }
catch (e) { if (e.shape?.data?.code === 'UNAUTHORIZED') promptOrgSwitch(); else throw e; }

Prevention

When it happens

Trigger: Calling swarm.nodes({ serverId }) where the server's organizationId differs from ctx.session.activeOrganizationId — e.g. a member of org A passing a serverId owned by org B, or the session's active organization not switched to the one owning the server.

Common situations: User belongs to multiple organizations and their active organization is the wrong one; stale client state after being moved between orgs; copying a serverId from another workspace's URL; deleted/re-created server rows with mismatched org ids.

Related errors


AI-assisted analysis of Dokploy/dokploy@546686ea35 (2026-08-27). Data as JSON: /api/errors/f180608fa9afb4da. Report an issue: GitHub.