nexu-io/open-design · error · DeployError
Enter a valid subdomain prefix, for example "demo".
Error message
Enter a valid subdomain prefix, for example "demo".
What it means
Thrown by normalizeCloudflarePagesDeploySelection in apps/daemon/src/deploy.ts:579 as `DeployError('Enter a valid subdomain prefix, for example "demo".', 400)` when the normalized domain prefix is empty. The prefix becomes the leftmost label of the custom hostname (`${prefix}.${zone}`), so an empty/invalid prefix yields no usable subdomain. `normalizeCloudflareDomainPrefix` strips anything that isn't a valid DNS label.
Source
Thrown at apps/daemon/src/deploy.ts:579
? status
: 'link-delayed';
}
function normalizeCloudflarePagesDeploySelection(input: unknown): CloudflarePagesDeploySelection | null {
if (!input || typeof input !== 'object') return null;
const source = input as JsonObject;
const rawZoneId = typeof source.zoneId === 'string' ? source.zoneId.trim() : '';
const rawZoneName = typeof source.zoneName === 'string' ? source.zoneName.trim() : '';
const rawPrefix = typeof source.domainPrefix === 'string' ? source.domainPrefix.trim() : '';
if (!rawZoneId && !rawZoneName && !rawPrefix) return null;
const zoneName = normalizeCloudflareZoneName(rawZoneName);
const domainPrefix = normalizeCloudflareDomainPrefix(rawPrefix);
if (!rawZoneId) throw new DeployError('Cloudflare zone is required for a custom domain.', 400);
if (!zoneName || !isValidCloudflareZoneName(zoneName)) {
throw new DeployError('Select a valid Cloudflare domain for the custom domain.', 400);
}
if (!domainPrefix) {
throw new DeployError('Enter a valid subdomain prefix, for example "demo".', 400);
}
return {
zoneId: rawZoneId,
zoneName,
domainPrefix,
hostname: `${domainPrefix}.${zoneName}`,
};
}
async function validateCloudflarePagesDeploySelection(config: DeployConfig, selection: CloudflarePagesDeploySelection | null): Promise<CloudflarePagesDeploySelection | null> {
if (!selection) return null;
const resp = await fetch(`${CLOUDFLARE_API}/zones/${encodeURIComponent(selection.zoneId)}`, {
headers: cloudflareHeaders(config),
});
const json = await readCloudflareJson(resp);
if (!resp.ok || json?.success === false) {
throw cloudflareError(json, resp.status, 'Cloudflare zone lookup failed.');
}View on GitHub (pinned to 5be4028344)
Solutions
- Provide a lowercase, alphanumeric, hyphen-separated prefix such as `demo`, `app`, or `staging`.
- Validate client-side: `/^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/` before submit.
- Make the prefix field required in the UI when a zone is selected.
Example fix
// before
normalizeCloudflarePagesDeploySelection({ zoneId: 'abc', zoneName: 'example.com', domainPrefix: 'Demo_App!' });
// after
normalizeCloudflarePagesDeploySelection({ zoneId: 'abc', zoneName: 'example.com', domainPrefix: 'demo' }); Defensive patterns
Strategy: validation
Validate before calling
const PREFIX_RE = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;
const prefix = typeof selection?.domainPrefix === 'string' ? selection.domainPrefix.trim() : '';
if (!PREFIX_RE.test(prefix)) {
return res.status(400).json({ error: 'Enter a valid subdomain prefix, e.g. "demo".' });
} Type guard
function isValidDomainPrefix(v: unknown): v is string {
return typeof v === 'string' && /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/.test(v);
} Try / catch
try {
await deployToCloudflarePages({ config, files, projectId, cloudflarePages: selection });
} catch (err) {
if (err instanceof DeployError && /subdomain prefix/i.test(err.message)) {
return res.status(400).json({ error: 'Subdomain prefix must be lowercase alphanumeric/hyphen.' });
}
throw err;
} Prevention
- Lowercase and validate the prefix in the input field as the user types.
- Reject underscores, spaces, uppercase, and leading/trailing hyphens client-side.
- Provide an inline example (e.g. 'demo') next to the field.
When it happens
Trigger: A custom-domain selection where `domainPrefix`, after trimming and normalization, is empty — e.g. the user submitted only zoneId+zoneName with no prefix, or the prefix contained only illegal characters that normalization removed.
Common situations: Prefix field left blank; user entered an invalid prefix (uppercase, underscores, spaces, punctuation) that normalizeCloudflareDomainPrefix reduced to empty string; the wildcard/root intent was misunderstood (the deploy requires a subdomain label).
Related errors
- Cloudflare zone is required for a custom domain.
- Select a valid Cloudflare domain for the custom domain.
- cloudflare_zone_inactive
- cloudflare_zone_not_full
- Cloudflare Pages project name could not be generated.
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/d5d96f21e501ad85.
Report an issue: GitHub.