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 forwardEnv and env.

What it means

A key may not appear in both forwardEnv (pass-through of existing host variables) and env (static values set for the subprocess). The static value in env would silently conflict with the forwarded host value, so the overlap is rejected at construction time.

Source

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

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

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Delete the key from forwardEnv if the fixed value in env should win.
  2. Delete it from env if the host value should be forwarded instead.
  3. Prefer credentialEnv for secret vars rather than duplicating across env/forwardEnv.

Example fix

// before
createACPV1({ env: { DEBUG: 'acp:*' }, forwardEnv: ['DEBUG'] });
// after
createACPV1({ env: { DEBUG: 'acp:*' } });
Defensive patterns

Strategy: validation

Validate before calling

const forwarded = new Set(implementation.forwardEnv ?? []);
const dup = Object.keys(implementation.env ?? {}).filter(k => forwarded.has(k));
if (dup.length > 0) throw new Error(`Keys in both forwardEnv and env: ${dup.join(', ')}`);

Type guard

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

Try / catch

try {
  const impl = createACPV1(settings);
} catch (err) {
  if (err instanceof Error && err.message.includes('both forwardEnv and env')) {
    console.error('Pick one source of truth: delete the key from forwardEnv or from env');
  }
  throw err;
}

Prevention

When it happens

Trigger: createACPV1 where a key in implementation.env is also listed in implementation.forwardEnv, e.g. env: {NODE_ENV:'production'} plus forwardEnv:['NODE_ENV'].

Common situations: Setting defaults in env while also listing the same var in forwardEnv, merging base config with per-environment overrides, or templated configs accumulating both lists over time.

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/661fb61939b92462. Report an issue: GitHub.