Summary
push_to_pull_request_branch safe outputs fail intermittently with:
remote: Duplicate header: 'Authorization'
fatal: unable to access 'https://github.com/.../': The requested URL returned error: 400
This happens on git ls-remote / git fetch / git push from the safe_outputs job.
Root cause
http.<url>.extraheader is a multi-valued git config key. In the safe_outputs job there were two credential sources both setting it:
- The checkout step uses
persist-credentials: true, which writes an http.<url>.extraheader = Authorization: Basic ... entry into .git/config.
- The handler actions/setup/js/push_to_pull_request_branch.cjs additionally injected a second
extraheader via GIT_CONFIG_COUNT / GIT_CONFIG_KEY_0 / GIT_CONFIG_VALUE_0 env vars (getGitAuthEnv).
Because the key is multi-valued, git sends both values, producing two Authorization headers on the wire → the server rejects the request with Duplicate header: 'Authorization' / HTTP 400.
create_pull_request.cjs already relies solely on the persisted .git/config credentials and does not inject getGitAuthEnv — push_to_pull_request_branch.cjs was the lone outlier.
A secondary issue: the persisted checkout credential used the default GITHUB_TOKEN rather than the resolved PR push token, so custom-PAT / cross-repo push configurations could persist the wrong credential.
Fix
- Stop the handler from injecting a second credential — rely on the credentials persisted in
.git/config by the checkout (consistent with create_pull_request.cjs).
- Persist the resolved PR push token (
resolvePRCheckoutToken) into the safe_outputs checkout so the single retained credential is the correct one (also fixes custom-PAT / cross-repo cases).
getGitAuthEnv remains in git_helpers.cjs for the other handlers that still need it (gh operations / cleaned-credential contexts).
Summary
push_to_pull_request_branchsafe outputs fail intermittently with:This happens on
git ls-remote/git fetch/git pushfrom thesafe_outputsjob.Root cause
http.<url>.extraheaderis a multi-valued git config key. In thesafe_outputsjob there were two credential sources both setting it:persist-credentials: true, which writes anhttp.<url>.extraheader = Authorization: Basic ...entry into.git/config.extraheaderviaGIT_CONFIG_COUNT/GIT_CONFIG_KEY_0/GIT_CONFIG_VALUE_0env vars (getGitAuthEnv).Because the key is multi-valued, git sends both values, producing two
Authorizationheaders on the wire → the server rejects the request withDuplicate header: 'Authorization'/ HTTP 400.create_pull_request.cjsalready relies solely on the persisted.git/configcredentials and does not injectgetGitAuthEnv—push_to_pull_request_branch.cjswas the lone outlier.A secondary issue: the persisted checkout credential used the default
GITHUB_TOKENrather than the resolved PR push token, so custom-PAT / cross-repo push configurations could persist the wrong credential.Fix
.git/configby the checkout (consistent withcreate_pull_request.cjs).resolvePRCheckoutToken) into thesafe_outputscheckout so the single retained credential is the correct one (also fixes custom-PAT / cross-repo cases).getGitAuthEnvremains ingit_helpers.cjsfor the other handlers that still need it (gh operations / cleaned-credential contexts).