Skip to content

Push rejected by the remote shows only "Git command exited with a non-zero status" #22430

Closed

Description

@err53

What happened

Clicking "Push and create PR" on a new branch fails with only:

Git command failed in GitVcsDriver.pushCurrentBranch.pushWithUpstream (~/.t3/worktrees//t3-xxxxxxxx): Git command exited with a non-zero status.

Nothing in the UI says why. Re-running the same push by hand showed that the remote refused the push for a reason the user could fix right away (a missing OAuth token scope). T3 Code gave no hint of that.

Diagnosis

The server (GitHub Enterprise) rejected the ref, and git reported it on stderr:

 ! [remote rejected] <branch> -> <branch> (Unable to determine if workflow can be created or updated due to timeout; `workflows` scope may be required.)
error: failed to push some refs to 'https://<ghe-host>/<org>/<repo>.git'

This happens because the remote URL is rewritten to HTTPS (url.<https>.insteadOf=git@<host>:), so git authenticates with the gh OAuth token through gh auth git-credential. That token has repo, read:org, gist, admin:public_key but not workflow. Without workflow, GHE has to check whether a new branch touches .github/workflows/, and on a very large monorepo that check timed out.

On the T3 side, apps/server/src/vcs/GitVcsDriverCore.ts keeps stderr inside the driver on purpose, because it can echo credentials. The only thing it passes on is a reason tag from classifyGitFailure. The ! [remote rejected] … (…) line passes GIT_DIAGNOSTIC_LINE_PATTERN (^\s+!\s). No entry in GIT_FAILURE_REASON_PATTERNS matches it, though, so reason is null and the user gets the generic "Git command exited with a non-zero status.".

GitCommandFailureReason on main (81dea78) is the same set as on v0.1.0: there is no reason for a push the remote rejected (! [remote rejected] or ! [rejected]). The same dead end therefore applies to any server-side refusal: missing workflow scope, push protection or secret scanning, pre-receive hooks, protected branches, and non-fast-forward pushes.

Suggestion: add a push_rejected_by_remote reason (or split it into push_rejected_non_fast_forward and push_rejected_by_remote), matched on git's own ! [rejected] / ! [remote rejected] lines. The UI could then say "The remote rejected the push. Run git push in a terminal to see the server's message." That keeps the stderr-redaction rule intact. Optionally, the server's parenthesized reason from git's ! [remote rejected] line could be passed through after sanitizing. Git writes that line itself, not as remote: hook output, but it is still text supplied by the server.

Steps to reproduce

  1. On a GitHub (Enterprise) remote accessed over HTTPS with a gh token that lacks the workflow scope, use a very large repo where GitHub's workflow-change check can time out. Alternatively, use any remote that rejects a ref, such as a pre-receive hook that declines everything or a protected branch.
  2. In T3 Code, on a worktree branch that has no upstream, click "Push and create PR".
  3. The error says only "Git command exited with a non-zero status." Running git push -u origin HEAD:refs/heads/<branch> in that worktree shows the actual ! [remote rejected] … (reason) line.

Version

Server 0.1.0 (the background service on the remote devbox). The desktop app version is unknown; the error comes from the server. t3 triage CLI: 0.1.0.

Environment

The desktop app connects over SSH to a Linux devbox (RHEL 9, kernel 5.14, x64) running a background-service T3 server. Node v26.8.2, git 2.52.0, gh with GitHub Enterprise and HTTPS via insteadOf.

Evidence

# server.trace.ndjson
{"name":"GitVcsDriver.pushCurrentBranch.pushWithUpstream","durationMs":6429.2,"attributes":{"git.args_count":4},...}
{"name":"pushCurrentBranch","exit":{"_tag":"Failure","cause":"GitCommandError: Git command failed in GitVcsDriver.pushCurrentBranch.pushWithUpstream (~/.t3/worktrees/<repo>/t3-xxxxxxxx): Git command exited with a non-zero status.\n    at pushCurrentBranch ...\n    at runStackedAction.runAction ...\n    at ws.rpc.git.runStackedAction ..."}}

# same push run by hand in the worktree
$ git push -u origin <branch>
 ! [remote rejected] <branch> -> <branch> (Unable to determine if workflow can be created or updated due to timeout; `workflows` scope may be required.)
error: failed to push some refs to 'https://<ghe-host>/<org>/<repo>.git'

Related issues

#22342 is the same pattern for GitLab (glab stderr hidden behind a generic message), but in a different code path. #11729 added sanitized hints for common VCS failures, but push rejections are not among them. #19219 ("publishing explains why the first push failed") is merged, but pushCurrentBranch.pushWithUpstream still returns the generic detail for a remote rejection on v0.1.0 and on main. No existing issue for push rejections was found.

Fix applied or workaround

Add the workflow scope to the gh token so GHE skips the workflow check: gh auth refresh -h <ghe-host> -s workflow. Then retry "Push and create PR".

Filed by

Claude Code (claude-opus-5-5) via t3 triage

Activity

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

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions