vercel/ai · error

ACP source.command must not be empty.

Error message

ACP source.command must not be empty.

What it means

When the ACP source is neither 'npm-locked' nor 'npm-simple', it is treated as a direct command source and source.command must be a non-empty string. An empty command gives the launcher nothing to spawn, so createACPV1 rejects it eagerly. Whitespace-only commands are also rejected via trim().

Source

Thrown at packages/harness-acp/src/v1/implementation.ts:71

export function validateACPV1Implementation(
  implementation: ACPImplementation,
): void {
  const { source } = implementation;
  if (source.type === 'npm-locked') {
    if (source.packageJson.length === 0) {
      throw new Error('ACP source.packageJson must not be empty.');
    }
    if (source.pnpmLockYaml.length === 0) {
      throw new Error('ACP source.pnpmLockYaml must not be empty.');
    }
    if (source.pnpmWorkspaceYaml?.length === 0) {
      throw new Error('ACP source.pnpmWorkspaceYaml must not be empty.');
    }
  } else if (source.type === 'npm-simple') {
    validateNpmSimpleSource({ source });
  } else if (source.command.trim().length === 0) {
    throw new Error('ACP source.command must not be empty.');
  }
  if (!EXECUTABLE_NAME_REGEXP.test(implementation.executable)) {
    throw new Error(
      `ACP executable must be a bare command name without a path; received ${JSON.stringify(implementation.executable)}.`,
    );
  }

  validateForwardEnvironment({ forwardEnv: implementation.forwardEnv });
  validateForwardEnvironment({ forwardEnv: implementation.credentialEnv });
  validateEnvironment({ env: implementation.env });
  const forwardedKeys = new Set(implementation.forwardEnv ?? []);
  const credentialKeys = new Set(implementation.credentialEnv ?? []);
  for (const key of credentialKeys) {
    if (forwardedKeys.has(key)) {
      throw new Error(
        `ACP runtime environment key ${JSON.stringify(key)} cannot be configured in both forwardEnv and credentialEnv.`,
      );
    }

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Set source.command to the actual executable command that speaks ACP.
  2. Verify which source branch your config falls into; if you meant an npm install, set type to 'npm-simple' or 'npm-locked' and fill its fields.
  3. Check upstream config loading (env substitution, YAML parsing) that produces the empty string.

Example fix

// before
createACPV1({ source: { command: process.env.ACP_CMD ?? '' } });
// after
const cmd = process.env.ACP_CMD;
if (!cmd) throw new Error('ACP_CMD is required');
createACPV1({ source: { command: cmd } });
Defensive patterns

Strategy: validation

Validate before calling

if (source.type !== 'npm-locked' && source.type !== 'npm-simple' && (!source.command || source.command.trim().length === 0)) {
  throw new Error('source.command is required for command sources');
}

Type guard

function hasCommandSource(source) {
  return source.type === 'npm-locked' || source.type === 'npm-simple' || (typeof source.command === 'string' && source.command.trim().length > 0);
}

Try / catch

try {
  const impl = createACPV1(settings);
} catch (err) {
  if (err instanceof Error && err.message === 'ACP source.command must not be empty.') {
    console.error('Set source.command to the ACP server executable command');
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling createACPV1 with a source object whose type is not 'npm-locked'/'npm-simple' and source.command is '', ' ', or missing from a loosely typed config object.

Common situations: Unset CLI/executable config in YAML/JSON settings, environment-variable substitution that resolves to '', or copying a provider config template without filling in the command.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/20692f43ce98db1f. Report an issue: GitHub.