{"record":{"id":"1563bfdb97f8fccc","repo":"Dokploy/dokploy","slug":"the-base-domain-must-start-with","errorCode":null,"errorMessage":"The base domain must start with \"*.\"","messagePattern":"The base domain must start with \"\\*\\.\"","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/services/preview-deployment.ts","lineNumber":248,"sourceCode":") => {\n\tconst previewDeploymentResult = await db.query.previewDeployments.findFirst({\n\t\twhere: and(\n\t\t\teq(previewDeployments.applicationId, applicationId),\n\t\t\teq(previewDeployments.pullRequestId, pullRequestId),\n\t\t),\n\t});\n\n\treturn previewDeploymentResult;\n};\n\nconst generateWildcardDomain = async (\n\tbaseDomain: string,\n\tappName: string,\n\tserverIp: string,\n\t_userId: string,\n): Promise<string> => {\n\tif (!baseDomain.startsWith(\"*.\")) {\n\t\tthrow new Error('The base domain must start with \"*.\"');\n\t}\n\tconst hash = `${appName}`;\n\tif (baseDomain.includes(\"sslip.io\")) {\n\t\tlet ip = \"\";\n\n\t\tif (process.env.NODE_ENV === \"development\") {\n\t\t\tip = \"127.0.0.1\";\n\t\t}\n\n\t\tif (serverIp) {\n\t\t\tip = serverIp;\n\t\t}\n\n\t\tif (!ip) {\n\t\t\tconst settings = await getWebServerSettings();\n\t\t\tip = settings?.serverIp || \"\";\n\t\t}\n","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/Dokploy/dokploy/blob/546686ea3587f12ec5652217dedd9f7960fb6d15/packages/server/src/services/preview-deployment.ts#L230-L266","documentation":"generateWildcardDomain requires the base domain argument to begin with the literal prefix \"*.\" because it builds a wildcard DNS entry (e.g. *.example.com) for preview deployments. Any base domain missing that prefix cannot be used to generate per-preview subdomains. The check is a simple string startsWith guard before any hashing or DNS work.","triggerScenarios":"Calling generateDomain/generateWildcardDomain (preview deployment domain generation) with a base domain like \"example.com\" or \"sslip.io\" instead of \"*.example.com\". Typically the value comes from server settings or an env-configured base domain field.","commonSituations":"Admin configured the preview-deployment base domain in server settings without the wildcard prefix; migrated config from a non-wildcard setup; typo like \"*.\" vs \"*\"; using a bare sslip.io domain without the leading \"*.\".","solutions":["Set the base domain to include the wildcard prefix, e.g. change \"example.com\" to \"*.example.com\" in the preview/deployment domain settings that feed this call","If using sslip.io-style domains, pass \"*.<ip>.sslip.io\" so the wildcard check passes and the IP-substitution branch can run","Add upfront validation in the settings UI/API so the base domain must match /^\\*\\./ before persisting"],"exampleFix":"// before\nconst domain = await generateWildcardDomain(\"mysite.com\", appName, ip, userId);\n// after\nconst domain = await generateWildcardDomain(\"*.mysite.com\", appName, ip, userId);","handlingStrategy":"validation","validationCode":"const isValidBaseDomain = (d: string) => /^\\*\\.[a-z0-9.-]+$/i.test(d.trim());\nif (!isValidBaseDomain(baseDomain)) throw new Error('base domain must look like *.example.com');","typeGuard":"const isWildcardDomain = (d: string): d is `*.${string}` => d.startsWith('*.');","tryCatchPattern":"try { await generateDomain(base, ...) } catch (e) { if (e instanceof Error && e.message.includes('must start with')) { /* re-prompt for *.domain */ } }","preventionTips":["Validate base domain format in settings forms before saving","Show a hint that the wildcard prefix is required for preview deployments"],"tags":["dns","wildcard-domain","preview-deployment","validation"],"backgroundTag":"invalid-domain-configuration","analyzedSha":"546686ea3587f12ec5652217dedd9f7960fb6d15","analyzedAt":"2026-08-27T05:18:58.095Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}