nexu-io/open-design · error · DeployError

cloudflare_zone_inactive

cloudflare_zone_inactive

Error message

Cloudflare custom domains require an active zone.

What it means

Thrown by validateCloudflarePagesDeploySelection in apps/daemon/src/deploy.ts:606 as `DeployError('Cloudflare custom domains require an active zone.', 400, { errorCode: 'cloudflare_zone_inactive' })` when the fetched zone has a `status` field that is not `'active'`. Cloudflare must finish provisioning the zone (nameservers verified) before it can host DNS records and a Pages custom domain, so pending/parked/moved zones are rejected. The guard is skipped only when `zone.status` is absent.

Source

Thrown at apps/daemon/src/deploy.ts:606

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.');
  }
  const zone = json?.result ?? json;
  const zoneName = normalizeCloudflareZoneName(zone?.name);
  if (!zoneName || zoneName !== selection.zoneName) {
    throw new DeployError('Cloudflare zone selection no longer matches the selected domain.', 400, {
      errorCode: 'cloudflare_zone_mismatch',
    });
  }
  if (zone?.status && zone.status !== 'active') {
    throw new DeployError('Cloudflare custom domains require an active zone.', 400, {
      errorCode: 'cloudflare_zone_inactive',
    });
  }
  if (zone?.type && zone.type !== 'full') {
    throw new DeployError('Cloudflare custom domains require a full DNS zone.', 400, {
      errorCode: 'cloudflare_zone_not_full',
    });
  }
  return { ...selection, zoneName };
}

async function setupCloudflarePagesCustomDomain({ config, projectId, selection, pagesDevUrl, priorMetadata }: { config: DeployConfig; projectId: string; selection: CloudflarePagesDeploySelection; pagesDevUrl: string; priorMetadata?: JsonObject | undefined }) {
  if (!config.projectName) throw new DeployError('Cloudflare Pages project name could not be generated.', 400);
  const pagesTarget = normalizeHostname(hostnameFromUrl(pagesDevUrl) || `${config.projectName}.pages.dev`);
  const marker = cloudflarePagesDnsMarker(projectId, config.projectName, pagesTarget);
  const base = {
    hostname: selection.hostname,
    url: `https://${selection.hostname}`,

View on GitHub (pinned to 5be4028344)

Solutions

  1. Complete Cloudflare nameserver setup for the zone (update NS records at the registrar) and wait for status to become 'active'.
  2. Verify status in the Cloudflare dashboard -> Overview for that zone.
  3. Retry the deploy/custom-domain setup after the zone shows active.

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

function isZoneInactive(err: unknown): boolean {
  return err instanceof DeployError && err.status === 400
    && (err as any).details?.errorCode === 'cloudflare_zone_inactive';
}

Try / catch

try {
  await deployToCloudflarePages({ config, files, projectId, cloudflarePages: selection });
} catch (err) {
  if (isZoneInactive(err)) {
    return res.status(400).json({
      error: 'The selected zone is not active yet. Complete nameserver setup in Cloudflare and retry.',
      errorCode: 'cloudflare_zone_inactive',
    });
  }
  throw err;
}

Prevention

When it happens

Trigger: The selected zone resolves and matches by name, but its Cloudflare-reported `status` is e.g. `pending` (nameservers not yet verified), `moved`, `deactivated`, or `initializing`.

Common situations: Newly added zone where nameserver verification hasn't completed; zone temporarily deactivated; zone in the process of being moved away from Cloudflare.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/b38c2f1a3b9ec996. Report an issue: GitHub.