vercel/ai · error

ACP runtime environment key ${JSON.stringify(key)} cannot be

Error message

ACP runtime environment key ${JSON.stringify(key)} cannot be configured in both credentialEnv and env.

What it means

A key may not appear in both credentialEnv (vars handled as credentials) and env (static subprocess values). Putting a credential-shaped variable into env would persist its secret value in plain config, so the overlap is rejected eagerly.

Source

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

  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.`,
      );
    }
  }
  for (const key of Object.keys(implementation.env ?? {})) {
    if (forwardedKeys.has(key)) {
      throw new Error(
        `ACP runtime environment key ${JSON.stringify(key)} cannot be configured in both forwardEnv and env.`,
      );
    }
    if (credentialKeys.has(key)) {
      throw new Error(
        `ACP runtime environment key ${JSON.stringify(key)} cannot be configured in both credentialEnv and env.`,
      );
    }
  }
}

export function createImplementationManifest({
  implementation,
}: {
  implementation: ACPImplementation;
}): string | undefined {
  const { source } = implementation;
  if (source.type === 'install-command') return undefined;
  if (source.type === 'npm-locked') {
    return source.packageJson;
  }
  return (
    JSON.stringify(

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Remove the key from env and let credentialEnv forward it from the host environment.
  2. Store the secret in the host environment or a secret manager rather than embedding it in settings.
  3. Scan config for the duplicated key before constructing the implementation.

Example fix

// before
createACPV1({ env: { GITHUB_TOKEN: 'ghp_x' }, credentialEnv: ['GITHUB_TOKEN'] });
// after
createACPV1({ credentialEnv: ['GITHUB_TOKEN'] }); // value supplied from host env
Defensive patterns

Strategy: validation

Validate before calling

const creds = new Set(implementation.credentialEnv ?? []);
const dup = Object.keys(implementation.env ?? {}).filter(k => creds.has(k));
if (dup.length > 0) throw new Error(`Secrets must not be inlined in env: ${dup.join(', ')}`);

Type guard

function envAndCredentialAreDisjoint(env, credentialEnv) {
  const cr = new Set(credentialEnv ?? []);
  return Object.keys(env ?? {}).every(k => !cr.has(k));
}

Try / catch

try {
  const impl = createACPV1(settings);
} catch (err) {
  if (err instanceof Error && err.message.includes('both credentialEnv and env')) {
    console.error('Remove the secret from env; supply it via the host environment');
  }
  throw err;
}

Prevention

When it happens

Trigger: createACPV1 where a key in implementation.env also exists in implementation.credentialEnv, e.g. env: {GITHUB_TOKEN: 'ghp_...'} plus credentialEnv:['GITHUB_TOKEN'].

Common situations: Hardcoding a token into env for local testing while credentialEnv is also configured, or generated configs that add secrets to env instead of referencing the host value.

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/05146e29b9ac61a7. Report an issue: GitHub.