vercel/ai · error

ACP source.packageJson must not be empty.

Error message

ACP source.packageJson must not be empty.

What it means

validateACPV1Implementation checks an ACPImplementation of type 'npm-locked' for required source artifacts. It throws when source.packageJson is an empty string, since launching the agent from a locked npm workspace requires package.json contents.

Source

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

    credentialEnv: settings.credentialEnv,
    env: settings.env,
  };
}

const EXACT_SEMVER_REGEXP =
  /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
const PACKAGE_NAME_REGEXP =
  /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/;
const EXECUTABLE_NAME_REGEXP = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
const ENVIRONMENT_VARIABLE_NAME_REGEXP = /^[A-Za-z_][A-Za-z0-9_]*$/;

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)}.`,
    );
  }

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Populate source.packageJson with the actual package.json file contents before calling createACPV1.
  2. Fix the file-read step so failures surface instead of silently yielding an empty string.
  3. If no lockfile workspace is needed, use a different source.type (e.g. 'npm-simple') with its required fields.

Example fix

// before
createACPV1({ implementation: { source: { type: 'npm-locked', packageJson: '', pnpmLockYaml: lock } } });
// after
const packageJson = await fs.readFile('package.json', 'utf8');
createACPV1({ implementation: { source: { type: 'npm-locked', packageJson, pnpmLockYaml: lock } } });
Defensive patterns

Strategy: validation

Validate before calling

if (source.type === 'npm-locked' && source.packageJson.length === 0) {
  throw new Error('source.packageJson is empty; load package.json contents before createACPV1');
}

Try / catch

try {
  createACPV1({ implementation });
} catch (error) {
  if (error instanceof Error && error.message.includes('packageJson must not be empty')) {
    throw new Error('Implementation packaging failed: package.json was not embedded');
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling createACPV1 with a 'npm-locked' source whose packageJson field is '' (empty string), typically from an unread/failed file load or a placeholder config.

Common situations: Build/packaging step that omitted package.json; reading the file with a helper that returned '' on error; hand-written config with an empty placeholder.

Related errors


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