Skip to content

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

Closed

Description

@brettheap

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_HINT only (scaffold-project.py:1760 and :1878).
  • At 155fcd2d the pushes go through _refused_push (scaffold-project.py:1710-1720, called at :1771 and :1890). It prints _login_remedy (:1684-1707) and then the hint when git's output holds one of NO_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-1679 says 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_push prints 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.

Direction.

Verify.

Size: S.

Lane: openreposhape-3 (openRepoShape-3)

Activity

  1. added this to the v1.2.0 milestone on Oct 19, 2026
  2. brettheap commented on Oct 19, 2026

    @brettheap
    ContributorAuthor

    (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.

    • What happens: git prints the no-login words (terminal prompts disabled, could not read Username, could not read Password) only over https. So where a url.<base>.insteadOf rule sends https://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 for fatal: Authentication failed: no remedy is named.
    • Where: scaffold-project.py's pushes and _login_remedy (about :1680-1706 at scaffold-project.py: a first scaffold's pushes and a --reuse-empty-repo re-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 head 155fcd2d). _login_remedy's ssh clause is printed only after the https no-login words, so it never describes a push refused over ssh.
    • Direction: when the push's own output shows ssh refused the key (for example Permission denied (publickey)), name the ssh clause's check (ssh -T against the user, host and port the rule names), then the --reuse-empty-repo re-run. Keep the ruleset hint for every other failure, as for the Authentication failed case above.
    • Verify: a first scaffold whose git rewrites https://github.com/ to an ssh URL, with a key the server refuses (a local sshd, or an ssh command stub that prints Permission 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)

  3. brettheap commented on Oct 19, 2026

    @brettheap
    ContributorAuthor

    CLAIMED — lane openRepoShape-3, session b30e8b49-f249-4668-adb1-1dbfa93c09e1@Eagle, 2026-10-19T18:35:42Z, for #993

    Logged in lanes/log/openRepoShape-3.md at 954a9e91c24bf02b2259173bd78cee190e663ca4.

    The three reads (lane-collision-protocol Rule 1):

    1. existing `CLAIMED —` comments on opensoft/openRepoShape#993:
       none
    2. `gh pr list --repo opensoft/openRepoShape --state all --search "#993"`, kept where the row or its body names `#993`:
    971	scaffold-project.py: a first scaffold's pushes and a `--reuse-empty-repo` re-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)	l3-915-scaffold-git-prompts	MERGED
    3. `git ls-remote --heads git@github.com:opensoft/openRepoShape` branches naming `993` as a whole token:
       none
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions