nexu-io/open-design · error · DeployError

Vercel token is required.

Error message

Vercel token is required.

What it means

Thrown by deployToVercel in apps/daemon/src/deploy.ts:390 as `DeployError('Vercel token is required.', 400)` when `config?.token` is falsy. The token is the Bearer credential used in the `Authorization` header for every Vercel API call (creating the deployment, polling status). Without it the function cannot make any authenticated request.

Source

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

      file: safePath,
      data: projectFile.buffer,
      contentType: projectFile.mime,
      sourcePath: safePath,
    });
  }
}

function isLinkedFolderProject(metadata: unknown) {
  return Boolean(
    metadata
      && typeof metadata === 'object'
      && typeof (metadata as { baseDir?: unknown }).baseDir === 'string',
  );
}

export async function deployToVercel({ config, files, projectId }: { config: DeployConfig; files: DeployFile[]; projectId: string }) {
  if (!config?.token) {
    throw new DeployError('Vercel token is required.', 400);
  }

  const createResp = await fetch(`${VERCEL_API}/v13/deployments${vercelTeamQuery(config)}`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${config.token}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      name: safeVercelProjectName(`od-${projectId}`),
      files: files.map((f) => ({
        file: f.file,
        data: Buffer.from(f.data).toString('base64'),
        encoding: 'base64',
      })),
      projectSettings: { framework: null },
    }),
  });

View on GitHub (pinned to 5be4028344)

Solutions

  1. Save a Vercel access token first via writeVercelConfig({ token }) (generate one at vercel.com -> Settings -> Tokens).
  2. Confirm vercel.json exists at deployConfigPath(VERCEL_PROVIDER_ID) and contains a non-empty `token` string.
  3. If using a team, also supply teamId/teamSlug so the token resolves to the right scope.

Example fix

// before
await deployToVercel({ config: { token: '' }, files, projectId });

// after
await writeVercelConfig({ token: process.env.VERCEL_TOKEN });
const config = await readVercelConfig();
await deployToVercel({ config, files, projectId });
Defensive patterns

Strategy: validation

Validate before calling

const config = await readVercelConfig();
if (!config.token) {
  return res.status(400).json({ error: 'Save a Vercel access token first.' });
}
await deployToVercel({ config, files, projectId });

Type guard

function hasVercelToken(config: Partial<DeployConfig>): config is DeployConfig & { token: string } {
  return typeof config.token === 'string' && config.token.length > 0;
}

Try / catch

try {
  await deployToVercel({ config, files, projectId });
} catch (err) {
  if (err instanceof DeployError && err.status === 400 && /Vercel token/i.test(err.message)) {
    return res.status(400).json({ error: 'Configure Vercel credentials before deploying.' });
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling `deployToVercel({ config, files, projectId })` where `config.token` is empty/undefined. This means `readVercelConfig()` returned an empty token (vercel.json absent or token field missing) and the user never saved credentials.

Common situations: Deploying before completing Vercel setup; vercel.json under OD_USER_STATE_DIR was deleted or corrupted; team migration wiped credentials; the UI allowed clicking Deploy before the token was persisted.

Related errors


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