Skip to content
Latchkey

Composer "COMPOSER_AUTH" / auth.json Missing - 401 on Private Packages

Composer authenticates to private registries and Git hosts using auth.json or the COMPOSER_AUTH environment variable. When neither is present in CI, requests to a private source come back 401/403 and the install fails.

What this error means

Composer fails on a private package or registry with an HTTP 401/403, or prompts for credentials it cannot read non-interactively. auth.json exists locally (and is gitignored), but CI has nothing.

composer output
  - Downloading acme/private (2.0.0)
The "https://repo.acme.dev/.../acme-private-2.0.0.zip" file could not be
downloaded (HTTP/2 401): authentication required
Invalid credentials for 'repo.acme.dev', aborting.

Common causes

auth.json is gitignored and absent in CI

Credentials live in a local, gitignored auth.json. CI never receives it, so private requests are unauthenticated and rejected.

COMPOSER_AUTH is unset or malformed

The COMPOSER_AUTH env var is the CI-friendly way to pass credentials, but if it is missing, has bad JSON, or names the wrong host, Composer cannot authenticate.

How to fix it

Pass credentials via COMPOSER_AUTH

Provide a JSON blob from a CI secret. Composer reads it without any committed file.

Terminal
export COMPOSER_AUTH='{"http-basic":{"repo.acme.dev":{"username":"ci","password":"'$REPO_TOKEN'"}}}'
composer install --no-interaction

Or write an auth.json from a secret

If you prefer the file form, materialise it from a secret in the job, not the repo.

Terminal
composer config --auth http-basic.repo.acme.dev ci "$REPO_TOKEN"
# writes ./auth.json (or use --global)

Confirm the host key matches the registry

  1. The JSON key under http-basic must equal the registry host exactly.
  2. Validate the JSON with php -r "json_decode(getenv('COMPOSER_AUTH'));".
  3. Re-run with -vvv to see which host returns 401.

How to prevent it

  • Inject COMPOSER_AUTH from CI secrets for every private source.
  • Keep auth.json gitignored; never commit live credentials.
  • Use a least-privilege, rotatable token scoped to the registry.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →