Skip to content

golangci-lint replays results cached from a deleted worktree, and the symptom names paths that no longer exist #745

Description

@stephrobert

mise run check goes red on a clean main right after a git worktree under .claude/worktrees/ is removed, and the red names files in that worktree.

Measured twice, 2026-09-07

Once by the maintainer in the morning (#736 records it: one commit away from excluding .claude/ in .golangci.yml), once in the afternoon after merging #743 and removing the worktree it was built in:

$ git worktree remove --force .claude/worktrees/fix-697
$ mise run check
[lint] level=warning msg="[runner] Can't process results by generated_file_filter processor: can't filter issue &result.Issue{FromLinter:\"gosec\", … Pos:token.Position{Filename:\"/home/bob/Projets/coucou/.claude/worktrees/fix-697/internal/proxy/forward_test.go\", … }: failed to get doc (lax) of file …: open /home/bob/Projets/coucou/.claude/worktrees/fix-697/internal/proxy/forward_test.go: no such file or directory"
[lint] level=warning msg="[runner/source_code] Failed to get line 343 for file /home/bob/Projets/coucou/.claude/worktrees/fix-697/internal/corpus/corpus.go: … no such file or directory"
… (twenty such lines)
[test] ok  	github.com/stephrobert/feint/tools/testplan	1.912s
[lint] ERROR task failed

The tests pass; only the lint task fails, on paths under a directory that no longer exists and that git ignores. The remedy is one command and adds nothing to the repository:

$ golangci-lint cache clean
$ mise run check
[lint] 0 issues.
local check passed

Why the symptom misleads

The red is on main, the paths are under .claude/, and the natural conclusion is "the linter is scanning the agents' worktrees, exclude them". That conclusion was one commit from being made once. It would be wrong twice over: the linter is not scanning those paths (they do not exist), it is replaying a result cache keyed on files it linted while the worktree existed; and a path exclusion in .golangci.yml would hide the artefact behind a permanent filter, and hide anything else that ever reports under that prefix.

Same family as #737, #739 and #740: an instrument whose verdict names the wrong subject.

Not established

Why the cache survives the worktree: whether the cache key is the absolute path of the package, whether golangci-lint run inside a worktree writes into the same cache directory as the main checkout, and whether a pinned version changes this. Nobody has read the cache layout.

What is asked

  1. Something that makes the remedy unnecessary or automatic on this repository, without excluding a path: a cache directory per worktree (GOLANGCI_LINT_CACHE), a cache clean in the lint task when a worktree was removed, or a documented step in .claude/skills/branch-and-pr beside "Work in a worktree of your own".
  2. A sentence in CONTRIBUTING.md or the skill naming the symptom, so the next reader recognises paths that no longer exist as a cache and not as a scan.
  3. Do not add .claude/ to the linter's exclusions.

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions