---
title: "MGS4009: commit left formatting stale"
description: Fires when a commit changes a Go file without leaving it correctly formatted, a commit-time question distinct from whether a file is formatted right now.
tags: [MGS4009, drift, formatting, gofmt, commit, hooks]
---

# MGS4009: commit left formatting stale

A commit changed a Go file, and `gofmt -l` reports that file as needing
reformatting. This is the drift-notice hooks' finding (`post-commit`, `pre-push`;
see the [git integration guide](../../../guides/integrations/git.md)), never a
build or CI failure - nothing here exits non-zero or blocks anything.

```text
commit 8f963f1 left formatting stale (gofmt would reformat): internal/foo.go
Reformat: magus run format:rw .
```

## Why this is not lint's question

`golangci-lint`'s formatters already answer "is this file formatted", against the
whole tree, right now. This code answers a different, narrower question: did THIS
COMMIT leave a file it touched unformatted, at the moment it was made. The two
disagree in both directions - a commit can touch an already-misformatted file and
leave it exactly as unformatted as it found it (lint's problem, not this commit's,
and this code stays silent), and a commit can format its own file correctly while
lint still fails on a dozen files elsewhere nobody touched today (also silent
here). Keying on the commit's own diff, not the tree, is what a notice fired once
per commit needs and a tree-wide lint pass does not give it.

## Resolution

Reformat and fold it in: `magus run format:rw .`, then commit the result. The
drift-notice hook names the exact fold command for the commit's amend safety
(unpublished and still HEAD: amend; unpublished but something now sits on top of
it: fixup + autosquash; already pushed: a new commit) - see [MGS4006](MGS4006.md),
whose fold-safety rules this class reuses unchanged. The two classes share one
notice per commit; this one just carries its own remedy line.

## What it checks, and what it does not

Scoped to the commit's changed files that the `format` target's own
`ctx.modifiesExistingFiles` declares governed, narrowed further to `.go` files.
Never writes: `gofmt -l`, never `-w`, so it cannot race a concurrent edit to the
same file the way a write could.

Markdown is governed by the same declaration and formatted with dprint, not gofmt,
and is not checked yet - a real gap, not a design choice, tracked alongside this
code rather than silently absent.

## See also

- [MGS4006](MGS4006.md): the sibling class in the same notice - a declared SOURCE
  changed with no matching declared OUTPUT change, generated-output drift rather
  than formatting.
- [MGS4007](MGS4007.md): a different question entirely - a target rewriting a
  declared source it did not declare as an edit, checked after a target RUNS, not
  after a commit is made.
