nexu-io/open-design · error · DeployError
Cloudflare account ID is required.
Error message
Cloudflare account ID is required.
What it means
Thrown by deployToCloudflarePages in apps/daemon/src/deploy.ts:480 as `DeployError('Cloudflare account ID is required.', 400)` — the second guard, immediately after the token check. The Cloudflare Pages API scopes project/asset/custom-domain operations under an account id (`account.id`), so a token alone is insufficient. Even if the token is valid, the deploy cannot proceed without the account ID.
Source
Thrown at apps/daemon/src/deploy.ts:480
status: typeof zone?.status === 'string' ? zone.status : undefined,
type: typeof zone?.type === 'string' ? zone.type : undefined,
}))
.filter((zone) => zone.id && zone.name),
cloudflarePages: normalizeCloudflarePagesConfigHints(config?.cloudflarePages),
};
}
export async function deployToCloudflarePages(input: { config: DeployConfig; files: DeployFile[]; projectId?: string; cloudflarePages?: unknown; priorMetadata?: JsonObject | undefined; target?: 'preview' | 'production' }) {
const {
config,
files,
projectId = '',
cloudflarePages = undefined,
priorMetadata = undefined,
target = 'production',
} = input || {};
if (!config?.token) throw new DeployError('Cloudflare API token is required.', 400);
if (!config?.accountId) throw new DeployError('Cloudflare account ID is required.', 400);
if (!config?.projectName) throw new DeployError('Cloudflare Pages project name could not be generated.', 400);
const customDomainSelection = await validateCloudflarePagesDeploySelection(
config,
normalizeCloudflarePagesDeploySelection(cloudflarePages),
);
await ensureCloudflarePagesProject(config);
const uploadToken = await getCloudflarePagesUploadToken(config);
await uploadCloudflarePagesAssets(uploadToken, files);
const form = new FormData();
const manifest: Record<string, string> = {};
for (const file of files) {
manifest[`/${file.file}`] = cloudflarePagesAssetHash(file);
}
form.append('manifest', JSON.stringify(manifest));View on GitHub (pinned to 5be4028344)
Solutions
- Save the Cloudflare account ID alongside the token via writeCloudflarePagesConfig({ token, accountId }).
- Find the account ID in the Cloudflare dashboard sidebar (right side on most pages) or via `GET /accounts` with the token.
- Gate the deploy on both token and accountId being non-empty before calling deployToCloudflarePages.
Example fix
// before
await deployToCloudflarePages({ config: { token: '...', accountId: '' }, files, projectId });
// after
await writeCloudflarePagesConfig({ token: '...', accountId: 'abc123' });
const config = await readCloudflarePagesConfig();
await deployToCloudflarePages({ config, files, projectId }); Defensive patterns
Strategy: validation
Validate before calling
const config = await readCloudflarePagesConfig();
if (!config.token) return res.status(400).json({ error: 'Token required.' });
if (!config.accountId) return res.status(400).json({ error: 'Account ID required.' });
await deployToCloudflarePages({ config, files, projectId }); Type guard
function hasCloudflareAccount(config: Partial<DeployConfig>): config is DeployConfig & { accountId: string } {
return typeof config.accountId === 'string' && config.accountId.trim().length > 0;
} Try / catch
try {
await deployToCloudflarePages({ config, files, projectId });
} catch (err) {
if (err instanceof DeployError && err.status === 400 && /account ID/i.test(err.message)) {
return res.status(400).json({ error: 'Enter your Cloudflare account ID.' });
}
throw err;
} Prevention
- Always persist accountId together with the token in one writeCloudflarePagesConfig call.
- Make both token and accountId fields required in the credentials form.
- Resolve accountId via GET /accounts if the user only knows the account name.
When it happens
Trigger: Calling `deployToCloudflarePages({ config, ... })` where `config.token` is non-empty but `config.accountId` is empty. Typically the user saved only a token (or the token field) and left the account ID blank.
Common situations: Config write persisted token but not accountId; user pasted the token into the wrong field; account ID field omitted in the UI form; accountId trimmed to empty due to whitespace-only input.
Related errors
- Cloudflare API token is required.
- Cloudflare zone is required for a custom domain.
- Select a valid Cloudflare domain for the custom domain.
- Enter a valid subdomain prefix, for example "demo".
- 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/19a149e557a609b1.
Report an issue: GitHub.