{"record":{"id":"25e20984e8eda293","repo":"Dokploy/dokploy","slug":"bad-request-25e209","errorCode":"BAD_REQUEST","errorMessage":"You cannot create a environment with the name 'production'","messagePattern":"You cannot create a environment with the name 'production'","errorType":"exception","errorClass":"TRPCError","httpStatus":400,"severity":"warning","filePath":"apps/dokploy/server/api/routers/environment.ts","lineNumber":50,"sourceCode":"\tenvironments,\n\tprojects,\n} from \"@/server/db/schema\";\n\nexport const environmentRouter = createTRPCRouter({\n\tcreate: protectedProcedure\n\t\t.input(apiCreateEnvironment)\n\t\t.mutation(async ({ input, ctx }) => {\n\t\t\ttry {\n\t\t\t\tawait checkEnvironmentCreationPermission(ctx, input.projectId);\n\t\t\t\tif (IS_CLOUD) {\n\t\t\t\t\tawait assertEnvironmentLimit(\n\t\t\t\t\t\tctx.session.activeOrganizationId,\n\t\t\t\t\t\tinput.projectId,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (input.name === \"production\") {\n\t\t\t\t\tthrow new TRPCError({\n\t\t\t\t\t\tcode: \"BAD_REQUEST\",\n\t\t\t\t\t\tmessage:\n\t\t\t\t\t\t\t\"You cannot create a environment with the name 'production'\",\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst environment = await createEnvironment(input);\n\n\t\t\t\tawait addNewEnvironment(ctx, environment.environmentId);\n\t\t\t\tawait audit(ctx, {\n\t\t\t\t\taction: \"create\",\n\t\t\t\t\tresourceType: \"environment\",\n\t\t\t\t\tresourceId: environment.environmentId,\n\t\t\t\t\tresourceName: environment.name,\n\t\t\t\t});\n\t\t\t\treturn environment;\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof TRPCError) {","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/Dokploy/dokploy/blob/546686ea3587f12ec5652217dedd9f7960fb6d15/apps/dokploy/server/api/routers/environment.ts#L32-L68","documentation":"Dokploy reserves the name 'production' at the project level and the create-environment procedure hard-blocks creating an environment literally named 'production' (case-sensitive exact match), throwing BAD_REQUEST. Note this is exact-match: 'Production' or 'production-2' pass this check.","triggerScenarios":"Calling environment.create with input.name === 'production' for any project. Projects already get an implicit production environment, so the name is reserved.","commonSituations":"Users or scripts trying to recreate the default production environment after deleting it; IaC/terraform-style provisioning that loops over a fixed list of environment names including 'production'.","solutions":["Use a different name such as 'prod', 'production-eu', or 'Production' (check is exact and case-sensitive)","If the default production environment was deleted accidentally, restore it or use the project's recreate/reset flow rather than re-creating by name"],"exampleFix":"// before\nawait trpc.environment.create.mutate({ name: 'production', projectId });\n\n// after\nawait trpc.environment.create.mutate({ name: 'prod', projectId });","handlingStrategy":"validation","validationCode":"const RESERVED = new Set(['production']);\nif (RESERVED.has(name)) name = `${name}-2`;","typeGuard":"const isReservedEnvName = (name: string) => name === 'production';","tryCatchPattern":"try {\n  await trpc.environment.create.mutate({ name, projectId });\n} catch (e) {\n  if (e instanceof TRPCClientError && e.message.includes(\\\"'production'\\\")) {\n    // pick another name and retry\n  }\n}","preventionTips":["Filter reserved names out of provisioning scripts","Remember projects already ship a default production environment"],"tags":["trpc","dokploy","environment","reserved-name","bad-request"],"backgroundTag":"reserved-name-conflict","analyzedSha":"546686ea3587f12ec5652217dedd9f7960fb6d15","analyzedAt":"2026-08-27T05:18:58.095Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}