github / github/gh-stack

`submit` loops forever after a failed stack delete: stale `pending_submit` modify state has no supported way out

Ouverte
#433 1 commentaire 1 réaction 0 personnes assignées Voir sur GitHub
bug topic: cli - submit
Langage dominant
Go
Étoiles
1.5k
Forks
70
Merge moyen
1 j 8 h
PR mergées (30 j)
7

Description

## Summary

After a `gh stack submit` fails with the HTTP 422 from #428, the modify session state left in `.git/gh-stack-modify-state` keeps pointing at the old stack, so **every subsequent `gh stack submit` retries the same impossible delete**. The error tells you to "Run `gh stack submit` again to retry", but the retry can never succeed, and no CLI command clears the state. The only escape is deleting an internal file by hand.

This is separate from #428: that issue is about the 422 itself. This one is about being unable to recover from it.

Compounding it, the failed `unstack` is **partially applied** — the open PRs really are removed from the stack on GitHub — so the repository is left in a state that matches neither the local metadata nor the pre-submit state.

## Reproduction

Starting from a submitted stack (`#10`) whose bottom layers are merged — `#101`, `#102` merged; `#103 → #104 → #105` open:

1. `gh stack modify`, insert a new branch mid-stack (between `#103` and `#104`), `Ctrl+S`. The modify applies locally.
2. `gh stack submit`, answer `Yes` to "Overwrite the existing stack on GitHub?"

```
Checking stack state...
Skipping 2 merged branches
? The local stack has been modified. Overwrite the existing stack on GitHub? Yes
⚠ Failed to delete existing stack: HTTP 422: Pull requests #101, #102 cannot be removed from this stack (.../stacks/10/unstack)
Run `gh stack submit` again to retry
```

3. Run `gh stack submit` again — and again. Identical output every time.

### The state that causes it

`.git/gh-stack-modify-state`:

```json
{
"schema_version": 1,
"phase": "pending_submit",
"prior_remote_stack_id": "900001",
...
}
```

`900001` is the internal id of stack `#10`. Every `submit` reads `prior_remote_stack_id` from this file and re-attempts the delete, which GitHub will never allow while the stack contains merged PRs.

Editing `.git/gh-stack` (removing the merged branch entries) does **not** help — the modify-state file is a second, independent store, and it is the one `submit` consults.

### The partial unstack

After the first failed submit, GitHub's side had already changed:

```
$ gh api repos/OWNER/REPO/stacks
stack 10 open=false prs=[101, 102]
```

The open PRs `#103`, `#104`, `#105` were successfully removed and now belong to no stack at all; only the two merged PRs remain. So `unstack` removed what it could and reported total failure. Local metadata still described all five.

## Available exits, none of them good

- `gh stack submit` — loops forever, as above.
- `gh stack modify --abort` — would discard the completed mid-stack insertion, which is the work the user is trying to keep.
- `gh stack unstack 10` — cannot help; GitHub refuses to remove the merged PRs, which is the original 422.
- Editing `.git/gh-stack` — no effect, wrong file.
- **`rm .git/gh-stack-modify-state`** — the only thing that works.

After removing that file, `gh stack submit` succeeded immediately and did the right thing:

```
✓ Created PR #106 for
✓ Updated base branch for PR #104 to
✓ Stack created on GitHub with 4 PRs (stack #11)
```

Which shows the operation was viable all along — only the stale `prior_remote_stack_id` was blocking it.

## Expected behavior

1. When the delete fails with a 422 that **cannot** succeed on retry (merged PRs can never be removed from a stack), don't advise retrying. Fall back to creating a new stack, or say plainly that the old stack cannot be dissolved and offer that as a choice.
2. Provide a supported way to clear a stuck `pending_submit` modify state without discarding the applied modify — e.g. a counterpart to `gh stack modify --abort` such as `--forget`/`--done` that drops the session but keeps the local restructuring.
3. Reconcile the partial unstack: if some PRs were removed and others refused, report that, and update local metadata to match what actually happened on the server.

## Related

- #428 — the 422 itself (new bottom branch after a merge). Same root cause, different trigger; this report covers the unrecoverable state afterwards.
- #382 — mid-stack insertion strands merged PRs.
- #372 — `unstack` reporting generic errors instead of the real API rejection.

## Environment

- `gh` 2.97.0
- `gh-stack` v0.1.0
- git 2.50.1 (Apple Git-155)
- macOS 26.6, darwin/arm64

Guide de contribution

Ouvrir le guide de contribution

Piste de recherche

Start with the `gh stack submit` handling for `.git/gh-stack-modify-state`, then compare the `gh stack modify --abort` and `gh stack unstack` flows. Reproduce the failed delete with the documented merged and open PR layout. Done means a failed partial unstack is reported and reconciled, and users have a supported recovery path that preserves the applied modification instead of retrying the stale `pending_submit` state.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
github, go
Domaine
cli
Type d'issue
Bug
Difficulté
4/5
Temps estimé
3-5 jours
Activité
Active
Clarté
Plutôt claire
Accessibilité débutants
55/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.