{"record":{"id":"dfd5e75a4279a18b","repo":"Dokploy/dokploy","slug":"unauthorized-dfd5e7","errorCode":"UNAUTHORIZED","errorMessage":"You don't have access to this destination.","messagePattern":"You don't have access to this destination\\.","errorType":"error_code","errorClass":"TRPCError","httpStatus":401,"severity":"error","filePath":"apps/dokploy/server/api/routers/volume-backups.ts","lineNumber":302,"sourceCode":"\t\t\t},\n\t\t})\n\t\t.input(\n\t\t\tz.object({\n\t\t\t\tbackupFileName: z.string().min(1),\n\t\t\t\tdestinationId: z.string().min(1),\n\t\t\t\tvolumeName: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.min(1)\n\t\t\t\t\t.regex(VOLUME_NAME_REGEX, VOLUME_NAME_MESSAGE),\n\t\t\t\tid: z.string().min(1),\n\t\t\t\tserviceType: z.enum([\"application\", \"compose\"]),\n\t\t\t\tserverId: z.string().optional(),\n\t\t\t}),\n\t\t)\n\t\t.subscription(async ({ input, ctx }) => {\n\t\t\tconst destination = await findDestinationById(input.destinationId);\n\t\t\tif (destination.organizationId !== ctx.session.activeOrganizationId) {\n\t\t\t\tthrow new TRPCError({\n\t\t\t\t\tcode: \"UNAUTHORIZED\",\n\t\t\t\t\tmessage: \"You don't have access to this destination.\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (input.serverId) {\n\t\t\t\tconst targetServer = await findServerById(input.serverId);\n\t\t\t\tif (targetServer.organizationId !== ctx.session.activeOrganizationId) {\n\t\t\t\t\tthrow new TRPCError({\n\t\t\t\t\t\tcode: \"UNAUTHORIZED\",\n\t\t\t\t\t\tmessage: \"You don't have access to this server.\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn observable<string>((emit) => {\n\t\t\t\tconst runRestore = async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\temit.next(\"🚀 Starting volume restore process...\");\n\t\t\t\t\t\temit.next(`📂 Backup File: ${input.backupFileName}`);","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/Dokploy/dokploy/blob/546686ea3587f12ec5652217dedd9f7960fb6d15/apps/dokploy/server/api/routers/volume-backups.ts#L284-L320","documentation":"Thrown by Dokploy's volume-backup subscription endpoint when the destination's organizationId differs from the caller's active organization id. Destinations (backup storage targets) are organization-scoped, so cross-organization access is rejected with UNAUTHORIZED before any streaming begins.","triggerScenarios":"Subscribing to the volume-backup events stream with a destinationId whose owning organization differs from ctx.session.activeOrganizationId — e.g. destination id from another workspace, or the session's active org was switched.","commonSituations":"Client state holding a destination selected before switching organizations; deep links embedding a destinationId from a shared link; multi-org users with similarly named destinations.","solutions":["Switch your active organization to the one that owns the destination","Re-select the destination from the current organization's list before subscribing","Verify destination.organizationId matches your session's activeOrganizationId"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const destination = await trpc.destination.byId.query(destinationId);\nif (destination.organizationId === session.activeOrganizationId) {\n subscribeToBackupEvents(destinationId);\n}","typeGuard":"const destinationInActiveOrg = (d: Destination, activeOrgId: string) => d.organizationId === activeOrgId;","tryCatchPattern":"catch (e) { if (e?.data?.code === 'UNAUTHORIZED' && /destination/.test(e.message)) refetchDestinations(); else throw e; }","preventionTips":["Clear selected destination on organization switch","Populate destination pickers from the active org only","Validate embedded ids from links against current org before subscribing"],"tags":["dokploy","trpc","authorization","unauthorized","backups","organizations","subscriptions"],"backgroundTag":"resource-ownership-mismatch","analyzedSha":"546686ea3587f12ec5652217dedd9f7960fb6d15","analyzedAt":"2026-08-27T05:18:58.095Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}