Skip to content

bug: rtk golangci-lint run returns exit 0 when lint issues are found (exit code masked) #2735

Description

@rueabc

Summary

rtk golangci-lint run prints the (correctly filtered) lint findings but exits 0 even when golangci-lint found issues and the raw binary would exit 1. The non-zero exit code is swallowed.

This is especially impactful because the Claude Code hook auto-rewrites golangci-lint run ...rtk golangci-lint run .... So any exit-code-based gate — pre-commit hooks, Makefile targets, && chains, and AI-agent "did lint pass?" checks — sees success while lint actually failed. The findings are visible in the output, but automation (and agents reasoning over exit codes) is misled into thinking the tree is clean.

Environment

  • rtk 0.42.4
  • golangci-lint 2.12.2 (config version: "2")
  • macOS (darwin, arm64)

Reproduce

T=$(mktemp -d) && cd "$T" && go mod init lintcheck >/dev/null
printf 'package main\n\nfunc main() {\n\tx := 1\n\tx = 2\n\t_ = x\n}\n' > main.go
printf 'version: "2"\nlinters:\n  default: none\n  enable: [ineffassign]\n' > .golangci.yml

rtk golangci-lint run ./...        ; echo "rtk filtered  -> exit=$?"
rtk proxy golangci-lint run ./...  ; echo "rtk proxy     -> exit=$?"
golangci-lint run ./...            ; echo "direct binary -> exit=$?"

Observed:

rtk filtered  -> exit=0    <-- masked (issue is printed, but exit says success)
rtk proxy     -> exit=1
direct binary -> exit=1

Expected

rtk golangci-lint run should propagate golangci-lint's exit code (1 when issues are found, 0 when clean) while keeping the compact output.

Scope (what I verified)

Only the golangci-lint handler is affected. These all propagate exit codes correctly:

  • rtk go test → 1 on test failure
  • rtk go build → 1 on compile error
  • rtk go vet → 1 on vet error
  • rtk grep → propagates

Workaround

Add golangci-lint to the hook exclude list so it runs raw (output is small, so ~no token cost):

[hooks]
exclude_commands = ["golangci-lint"]

Related

Likely a concrete instance of the concern in #1313 (honest account of silent failures in agent contexts). Distinct here: it's exit-code propagation, not output truncation.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions