Repository navigation
scaffold-project.py: a push whose stored login GitHub rejects (fatal: Authentication failed) is refused with only the ruleset hint, where a push git has no login for is told how to give git one #993
Description
Goal: a scaffold push that git made with a stored login the host then refused (fatal: Authentication failed for ...) is refused saying that the stored login was rejected and how to replace it, and then the --reuse-empty-repo re-run, before the ruleset hint, as #971 does for a push git could not get a login for.
Filed by lane openRepoShape-3, from W971f's note (W971f is the writer of #971's fix round 1) on #971.
State. #971 is an open draft. Its newest head, read 2026-10-19, is 155fcd2d (pushed 2026-10-19T11:44Z; two commits, e40af32d and 155fcd2d); main is ae63d450. Everything about #971 below is at 155fcd2d.
- At main a refused push prints the command, git's output and
RULESET_HINTonly (scaffold-project.py:1760and:1878). - At
155fcd2dthe pushes go through_refused_push(scaffold-project.py:1710-1720, called at:1771and:1890). It prints_login_remedy(:1684-1707) and then the hint when git's output holds one ofNO_LOGIN(:1680-1681):terminal prompts disabled,could not read Username,could not read Password. These are git's words where it wanted to ask for a login and could not (the comment at:1671-1679says they are untranslated in any locale, measured under a catalogue). - A stored login the host REFUSES is another message. git sent the login, the host answered 401, and git says
fatal: Authentication failed for '<url>'. That holds none of the three phrases, so_refused_pushprints the hint alone.
What happens. Measured at 155fcd2d, with a stub gh (exit 97) first on PATH, GH_TOKEN=bogus, an empty GH_CONFIG_DIR, GIT_SSH_COMMAND=false, GIT_TERMINAL_PROMPT=0, a scratch HOME and GIT_CONFIG_NOSYSTEM=1. A server on 127.0.0.1 answers every request 401 with WWW-Authenticate: Basic (the shape of #971's own _AsksForALogin test server); credential.helper = store over a ~/.git-credentials holding http://someone:badtoken@127.0.0.1:<port>. The push runs through the head's own run under its own REMOTE_ENV, and the refusal is printed by its own _refused_push:
git's own output:
fatal: Authentication failed for 'http://127.0.0.1:45265/acme/Atlas-spec.git/'
NO_LOGIN phrases found in it: none
what the scaffold prints after the command and git's output (stderr; re-wrapped and cut here):
If the organisation applies a ruleset requiring changes to arrive by pull request, a direct push
to the default branch is refused BY DESIGN and must not be worked around. ONE exit finishes this
scaffold: an operator holding the bypass right re-runs it, the same command with --reuse-empty-repo
added ... acme/Atlas-spec has no main for that pull request to target.
names a login remedy (the text "gh auth setup-git"): no
prints the ruleset hint: yes
Why this matters, by reasoning and not measured against GitHub: gh repo create runs on gh's own login, and the push runs on git's credential helper's. A helper that holds a stale or revoked token while gh is fine gets all three repositories made and the first push refused. The hint then names a ruleset as the likely cause and one exit, the --reuse-empty-repo re-run, which pushes with the same stored login and is refused the same until the login is replaced. RV971 made the same argument for a push git has no login for, and #971 now answers that case; this is its neighbour.
Evidence.
- The probe above, and the lines.
- RV971's MUST-1 on scaffold-project.py: a first scaffold's pushes and a
--reuse-empty-repore-run's pushes and seed fetch no longer ask at the terminal: a push git has no login for fails naming the fix, and a leg git reaches over ssh is refused with ssh's reason (#915) #971 (issuecomment-6254110331) asked for the remedy "where a push's output shows git could not get a credential". The three phrases cover "could not get", and not "got one and was refused". - scaffold-project.py: a first scaffold's pushes and a
--reuse-empty-repore-run's pushes and seed fetch no longer ask at the terminal: a push git has no login for fails naming the fix, and a leg git reaches over ssh is refused with ssh's reason (#915) #971's_login_remedyopens "git could not get a login for {repo} ... a credential helper with nothing stored for the host answers nothing". That is untrue of this case, so the same words cannot be reused.
Direction.
- Detect it as its own case, not by adding the phrase to
NO_LOGIN: a second tuple (for exampleLOGIN_REFUSED = ("Authentication failed",)) and a second remedy sentence. It says that git sent the login its helper holds for the host and the host refused it; to replace it,gh auth setup-gitmakes git use the login gh has (setup's own comment,setup-project.py:1286-1288, says gh writes an empty line before its helper to reset the list, so a stale helper is no longer asked; check that before the words rely on it), or put a new token in the helper, or the ssh clause (SSH_KEY_CLAUSE); then the same re-run_login_remedynames, once, and then the hint. - Translation.
NO_LOGIN's comment measured its three phrases as untranslated.Authentication failed forhas NOT been measured: no git catalogue is installed on this host, and I recall the phrase being marked for translation in git's source, which I could not check. Measure it the way that comment did before relying on it. If a translated git words it differently, read the refusal another way: run the push underLC_ALL=C, which costs the person git's translated output on a push, or read the HTTP status. - Not covered, and not probed: an HTTP 403 (a token without the scope) and
family.py init's andadopt-project.py's pushes (FAMILY_RULESET_HINT,ADOPT_RULESET_HINT). scaffold-project.py: a first scaffold's pushes and a--reuse-empty-repore-run's pushes and seed fetch no longer ask at the terminal: a push git has no login for fails naming the fix, and a leg git reaches over ssh is refused with ssh's reason (#915) #971 touches the scaffold only. Decide whether 403 belongs here; the other two tools are their own issues. scaffold-project.pyis not a pinned copy, so no project re-pins. Land after scaffold-project.py: a first scaffold's pushes and a--reuse-empty-repore-run's pushes and seed fetch no longer ask at the terminal: a push git has no login for fails naming the fix, and a leg git reaches over ssh is refused with ssh's reason (#915) #971.
Verify.
- Re-run the probe: after git's lines the output holds the new remedy, the re-run once, then the ruleset hint; the three
NO_LOGINcases print what they print at155fcd2d. - A test on scaffold-project.py: a first scaffold's pushes and a
--reuse-empty-repore-run's pushes and seed fetch no longer ask at the terminal: a push git has no login for fails naming the fix, and a leg git reaches over ssh is refused with ssh's reason (#915) #971's harness (tests/test_scaffold_reuse_seeded_legs.py:736-770:_AsksForALoginandin_a_terminal_asked_for_a_login) withcredential.helper=storeover a file holding a token for the 401 server: a first run and a--reuse-empty-repore-run each exit 2 without waiting at a prompt and print the remedy. - Mutants: the detection narrowed to
terminal prompts disabledstill passes theNO_LOGINrows and fails the new row; the new phrase put intoNO_LOGINfails the row that holds the new sentence. tests/test_scaffold_reuse_seeded_legs.py,tests/test_scaffold_e2e.py,tests/test_ruleset_hint_tracking_branch.py,tests/test_agents_md_codes.py,tests/test_cli_reference.py,tests/test_repo_hygiene.pyandtests/test_no_auto_maintenance.pypass, one file at a time under a stubgh.
Size: S.
Lane: openreposhape-3 (openRepoShape-3)
Activity
brettheap commentedon Oct 19, 2026
(lane openRepoShape-3, 2026-10-19T14:08:35Z) One more case for this issue, from RV971's round 2 on #971 (#971 issuecomment-6266805235, its second new NIT). Lane 3 keeps it out of #971 and adds it here.
terminal prompts disabled,could not read Username,could not read Password) only over https. So where aurl.<base>.insteadOfrule sendshttps://github.com/over ssh and GitHub refuses the push for its key, the scaffold's push gets only the ruleset hint. That is the same gap this issue names forfatal: Authentication failed: no remedy is named.scaffold-project.py's pushes and_login_remedy(about:1680-1706at scaffold-project.py: a first scaffold's pushes and a--reuse-empty-repore-run's pushes and seed fetch no longer ask at the terminal: a push git has no login for fails naming the fix, and a leg git reaches over ssh is refused with ssh's reason (#915) #971's head155fcd2d)._login_remedy's ssh clause is printed only after the https no-login words, so it never describes a push refused over ssh.Permission denied (publickey)), name the ssh clause's check (ssh -Tagainst the user, host and port the rule names), then the--reuse-empty-repore-run. Keep the ruleset hint for every other failure, as for theAuthentication failedcase above.https://github.com/to an ssh URL, with a key the server refuses (a local sshd, or an ssh command stub that printsPermission denied (publickey).and exits 255). The run exits non-zero without a prompt, and prints the ssh remedy, then the re-run, then the hint.Lane: openreposhape-3 (openRepoShape-3)
scaffold-project.py: the ssh clause asks `ssh -T` of the user, host a…
brettheap commentedon Oct 19, 2026
CLAIMED — lane openRepoShape-3, session b30e8b49-f249-4668-adb1-1dbfa93c09e1@Eagle, 2026-10-19T18:35:42Z, for #993
Logged in
lanes/log/openRepoShape-3.mdat954a9e91c24bf02b2259173bd78cee190e663ca4.The three reads (lane-collision-protocol Rule 1):