[BUG] Routine push to main returns HTTP 403 from git proxy despite "Allow unrestricted branch pushes" being enabled

Status Fixed / completed
Reported on v2.1.138
Maintainer reply ✓ Yes — ashwin-ant
Activity 7 comments · opened May 11, 2026 · closed May 14, 2026
💡 Likely answer: A maintainer (ashwin-ant, collaborator) responded on this thread — see the highlighted reply below.

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

A routine configured with "Allow unrestricted branch pushes" enabled cannot push to main. The Anthropic git proxy returns HTTP 403 on git push origin main, even though the setting that should permit this is on.

This appears related to #24535 (proxy restricts pushes to claude/* only) and #44949 (inconsistent enforcement of the "Allow unrestricted branch pushes" setting), but is a clean minimal repro of the inverse case: setting is ON, push to main is still blocked.

What Should Happen?

With "Allow unrestricted branch pushes" enabled for the repository, git push origin main should succeed and the commit should land on origin/main.

Error Messages/Logs

The push fails with HTTP 403 from the proxy. Full trace below.
Trace log (/tmp/push-trace.log)
++ git fetch origin main
From http://127.0.0.1:44229/git/<branch>
 * branch            main       -> FETCH_HEAD
++ git checkout main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
++ git pull --ff-only origin main
From http://127.0.0.1:44229/git/<branch>
 * branch            main       -> FETCH_HEAD
Already up to date.
++ git add drafts/
++ git commit -m 'Push test 2026-05-11T20:13:41Z'
[main 3d56787] Push test 2026-05-11T20:13:41Z
 1 file changed, 3 insertions(+)
 create mode 100644 drafts/push-test-20260511-201332.md
++ git push origin main
error: RPC failed; HTTP 403 curl 22 The requested URL returned error: 403
send-pack: unexpected disconnect while reading sideband packet
fatal: the remote end hung up unexpectedly
Everything up-to-date
++ echo PUSH_EXIT_CODE:1
PUSH_EXIT_CODE:1

Steps to Reproduce

Steps to reproduce

Create a routine with "Allow unrestricted git push — Let the agent push to any branch on this repo, including the default branch." set to True.

Give these instructions to the routine:

You are running a push test. Do exactly the steps below.

Step 1 — Write a test file

Create drafts/push-test-<timestamp>.md with a short test message.

Step 2 — Commit and attempt to push to main

Run these commands exactly:

set -x
exec > >(tee -a /tmp/push-trace.log) 2>&1

git fetch origin main
git checkout main
git pull --ff-only origin main
git add drafts/
git commit -m "Push test"
git push origin main

Step 3 — Report exit code and trace log

Hard rules

  • The push command is exactly git push origin main.
  • Do not add flags, do not use a refspec mapping, do not retry on failure,

do not fall back to a claude/* branch.

Claude Model

Sonnet (default)

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.138

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

_No response_

View original on GitHub ↗

7 Comments

github-actions[bot] · 3 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/57689
  2. https://github.com/anthropics/claude-code/issues/57829
  3. https://github.com/anthropics/claude-code/issues/57356

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

ClintHuijbers · 3 months ago

Another autonomous-routine cascade observation, independent from the original repro and from the Falcon trading-bot cascade on 2026-05-11/12. Adding it in case it helps prioritize.

Setup: Cloud-scheduled Claude Code Routine fires on cron, runs an end-of-day trading bookkeeping workflow that publishes JSON artifacts to a shared cross-repo knowledge base and then commits + pushes EOD state to its own bot repo main.

Symptom on 2026-05-12 ~20:00 UTC (daily-summary fire):

  • Routine container initialized fine — not a #54260 silent-init-fail case.
  • Routine ran far enough to publish artifacts to the KB repo successfully (separate origin, separate auth path) — KB commit lands cleanly.
  • Routine then attempted commit + push to its own bot repo main and failed silently. No corresponding commit on main, no fallback branch on remote — commit was lost on container reap before the in-script PR-fallback path completed its merge poll.
  • The bot uses a _safe-push v2.1.1 wrapper that retries on HTTP 403 / git-receive-pack sideband-disconnect and falls back to a feature branch + gh pr create + gh pr merge --squash poll-retry. On this fire the fallback branch was either never created or the container terminated before the wrapper exited cleanly.
  • Same wrapper on the same routine fired without issue on the next day — intermittent, matches this issue's repro fingerprint.

Why this is a stronger signal than a manual git push repro:

  • Autonomous routines run unattended on cron. A silent commit-loss has cascading downstream effects — next day's preflight reads stale state, conservative-mode kicks in, opportunity cost accumulates.
  • Two sibling autonomous projects on independent GitHub accounts hit the same fingerprint same week (Falcon 2026-05-11/12, Hawkeye 2026-05-12). Both have working _safe-push wrappers with 403 handling — failure is upstream of the wrapper's intercept.
  • Compounded by Anthropic Opus 4.7 elevated-errors incident 2026-05-12 18:51-23:58 UTC, which overlaps two of the four daily routine fire-times — multi-vector failure mode for autonomous workflows.

Operator-side mitigation adopted (not a substitute for the fix):

  • Session-preamble: git fetch --all && git branch -r --no-merged origin/main | grep <bot-fallback-pattern> — surfaces unmerged fallback branches before any new work.
  • Daily-summary routine adds an audit step at routine layer: emits a tagged log line when fallback branches are detected.
  • Bulk ff-merge is unsafe: older fallback branches forked from pre-current-main contain stale state and would revert subsequent work if merged blindly. Surgical cherry-pick of memory/ data files only.

Ask: is there a planned fix horizon for #58141? Even an exposed ended_reason distinguishable from #54260's silent-success run_once_fired would let operator-loop wrappers detect this failure mode programmatically rather than via remote-branch grep.

ashwin-ant collaborator · 3 months ago

This should be fixed now.

ClintHuijbers · 3 months ago

Additional evidence from an autonomous trading-bot deployment hitting this issue continuously since 2026-05-11. Refined bug model based on empirical scope-narrowing across multiple repos and branches.

Refined scope: source-repo + default-branch only

In our deployment, the proxy block applies specifically to the default branch of the trigger's sources git_repository — NOT all main pushes. Same routine, three push targets, three different outcomes:

| Push target | Outcome |
|---|---|
| <trigger.source.repo>/main (default branch of source) | 403 / sideband disconnect (blocked) |
| <trigger.source.repo>/<feature-branch> (same repo, non-default branch) | succeeds |
| <other-repo>/main (different repo, e.g. a shared KB the routine also pushes to) | succeeds |

All 8 of our cloud triggers have allow_unrestricted_git_push: true configured in sources[].git_repository, verified via RemoteTrigger API. The setting is correctly enabled; the proxy ignores it for the source-repo default-branch path specifically.

Error signature (matches OP exactly)

error: RPC failed; HTTP 403 curl 22 The requested URL returned error: 403
send-pack: unexpected disconnect while reading sideband packet
fatal: the remote end hung up unexpectedly

Workaround that works

Push to a feature branch from the routine, then open a draft PR. The operator (or a follow-up routine) ff-merges/cherry-picks to main. Our _safe-push wrapper does this automatically on 403/500.

Ruled out (operator-side empirical checks)

  • GitHub branch protection on source repo: API returns HTTP 403 "Upgrade to GitHub Pro or make this repository public to enable this feature" — feature is paywalled, literally unavailable on our private Free-tier repo. Cannot be the cause.
  • Operator-side push permission: operator's direct git push origin main from local works continuously throughout the same incident window.
  • Routine allow_unrestricted_git_push config: verified true on every trigger.

Operational impact

Real one — for autonomous routines that need to commit work to their source repo's main (daily summaries, EOD logs, state persistence), every fire requires operator-loop merge of fallback branches. Two consecutive trading days (2026-05-11 → 2026-05-12) lost to CAUTIOUS_MODE skips when the cascade prevented EOD heartbeat commits from landing on main, even though the work itself was preserved on fallback branches.

The bug surface is narrower than "all main pushes broken" — only source-repo + default branch — but for source-repo-state-persistence use cases it's a complete block.

Hope this helps narrow the proxy logic. Happy to provide more specific trigger configs or git-proxy log lines if useful.

ClintHuijbers · 3 months ago

Thanks @ashwin-ant — will verify on next two natural cron fires (a daily-summary at 20:03Z tonight + a higher-stakes trading-routine fire tomorrow 13:45Z) and report back. For reference, our most recent fire at 2026-05-14 15:01Z still hit the 403 / sideband-disconnect pattern (commit landed on a fallback branch), so the fix either landed after that fire or doesn't propagate to existing triggers / requires routine recreation.

Will report observability:

  • Direct push to origin/main → fix verified
  • Fallback branch created → fix not yet propagated

Holding our operator-loop merge discipline until both fires confirm clean. Will comment with the verification outcome.

ClintHuijbers · 3 months ago

Verifying — both natural cron fires landed clean on Hawkeye after your fix:

  • 2026-05-14 pre-close 19:32Z (cron 19:27Z, +5min lag) — commit 2cc3783, direct-to-main push succeeded, heartbeat row written
  • 2026-05-14 daily-summary 20:14Z (cron 20:03Z, +11min lag) — commit cec50fc, direct-to-main push succeeded, heartbeat row written

Both pushed directly to origin/main without falling back to the hawkeye-bot/<routine>-<date> fallback-branch path that we'd been seeing on every push 2026-05-11 through 2026-05-12. Hawkeye is now 8 of 8 routine fires clean on 5/13 + 5/14 vs 4 of 8 on 5/11–5/12 (mixed #58141 push-403 + apparent silent-fail symptoms).

The clearing is sharp and coincident with your fix landing. Continuing to monitor through this week — will reopen or file fresh if anything regresses. Thanks for the quick turnaround.

github-actions[bot] · 1 month ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.