{"record":{"id":"ed2a7fb6849c8dd1","repo":"Dokploy/dokploy","slug":"unauthorized-ed2a7f","errorCode":"UNAUTHORIZED","errorMessage":"You need to use a server to create a compose","messagePattern":"You need to use a server to create a compose","errorType":"exception","errorClass":"TRPCError","httpStatus":401,"severity":"error","filePath":"apps/dokploy/server/api/routers/compose.ts","lineNumber":98,"sourceCode":"import { createTRPCRouter, protectedProcedure } from \"../trpc\";\nimport { audit } from \"../utils/audit\";\n\nexport const composeRouter = createTRPCRouter({\n\tcreate: protectedProcedure\n\t\t.input(apiCreateCompose)\n\t\t.mutation(async ({ ctx, input }) => {\n\t\t\ttry {\n\t\t\t\tconst environment = await findEnvironmentById(input.environmentId);\n\t\t\t\tconst project = await findProjectById(environment.projectId);\n\n\t\t\t\tawait checkServiceAccess(ctx, project.projectId, \"create\");\n\n\t\t\t\tconst webServerSettings = await getWebServerSettings();\n\t\t\t\tif (\n\t\t\t\t\t(IS_CLOUD || webServerSettings?.remoteServersOnly) &&\n\t\t\t\t\t!input.serverId\n\t\t\t\t) {\n\t\t\t\t\tthrow new TRPCError({\n\t\t\t\t\t\tcode: \"UNAUTHORIZED\",\n\t\t\t\t\t\tmessage: \"You need to use a server to create a compose\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (project.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 are not authorized to access this project\",\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (input.serverId) {\n\t\t\t\t\tconst accessibleIds = await getAccessibleServerIds(ctx.session);\n\t\t\t\t\tif (!accessibleIds.has(input.serverId)) {\n\t\t\t\t\t\tthrow new TRPCError({\n\t\t\t\t\t\t\tcode: \"UNAUTHORIZED\",\n\t\t\t\t\t\t\tmessage: \"You are not authorized to access this server\",\n\t\t\t\t\t\t});","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/Dokploy/dokploy/blob/546686ea3587f12ec5652217dedd9f7960fb6d15/apps/dokploy/server/api/routers/compose.ts#L80-L116","documentation":"Thrown by `compose.create`: in Dokploy Cloud (IS_CLOUD) or when the self-hosted instance has remoteServersOnly enabled in web server settings, a compose must be attached to an explicit serverId — there is no default local server to deploy to.","triggerScenarios":"Calling compose.create without input.serverId while IS_CLOUD=true or admin settings set remoteServersOnly.","commonSituations":"Custom scripts or older clients built before the remote-servers-only setting; admin enabling remoteServersOnly and existing UI flows not yet supplying a server; using the cloud version with a self-hosted-style payload.","solutions":["Pass a serverId owned by your organization in the compose create input","If self-hosted and you want local deployment, disable remoteServersOnly in the web server settings","Pick a default server in the UI before creating the compose"],"exampleFix":"// before\nawait trpc.compose.create.mutate({ name: 'api', projectId, ... });\n\n// after\nawait trpc.compose.create.mutate({ name: 'api', projectId, serverId: 'srv_xxx', ... });","handlingStrategy":"validation","validationCode":"const servers = await trpc.server.all.query();\nif (!servers.length) throw new Error('Create/attach a server before adding composes');\ninput.serverId ??= servers[0].serverId;","typeGuard":"function hasServerId<T extends { serverId?: string }>(i: T): i is T & { serverId: string } {\n  return typeof i.serverId === 'string' && i.serverId.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Require server selection in the compose form when cloud/remote-only","Check remoteServersOnly setting before scripting compose creation","Keep at least one healthy server per organization"],"tags":["dokploy","trpc","compose","cloud-only","server-required"],"backgroundTag":"cloud-required-field-missing","analyzedSha":"546686ea3587f12ec5652217dedd9f7960fb6d15","analyzedAt":"2026-08-27T05:18:58.095Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}