Skip to content

fix(go): keep go list diagnostics out of the default output - #11816

Merged
jdx merged 1 commit into
jdx:mainfrom
JamBalaya56562:fix/go-list-stderr-capture
Aug 9, 2026
Merged

jdx merged 1 commit into
jdx:mainfrom
JamBalaya56562:fix/go-list-stderr-capture

Conversation

@JamBalaya56562

@JamBalaya56562 JamBalaya56562 commented Aug 9, 2026 •

Copy link
Copy Markdown
Contributor

Closes #5189.

What is left of the problem

Most of that report is already fixed. Version resolution goes through $GOPROXY now, so on a default setup go is never spawned and none of the reporter's three cases produce output. Measured on v2026.8.2 with their exact examples:

$ mise ls-remote go:github.com/erning/gorun          # case 1
0.0.0-20230315023741-02445e31634f
$ mise ls-remote go:rsc.io/rf                        # case 2
0.0.0-20260710193434-85dbf8d53aee
$ mise ls-remote go:golang.org/x/tools/cmd/godoc     # case 3
0.1.0-deprecated

The GOPROXY=direct fallback is the part that still leaks, and it reproduces on one of the reporter's own tools:

$ mise ls-remote go:github.com/davidrjenni/reftools/cmd/fillswitch
go: module github.com/davidrjenni/reftools/cmd/fillswitch: no matching versions for query "latest"
go: module github.com/davidrjenni/reftools/cmd: no matching versions for query "latest"
0.0.0-20250907133731-34b10582faa4

Splitting the streams locates it — the version is the only thing on stdout, and those two lines come from go itself:

$ mise ls-remote <same> 2>/dev/null
0.0.0-20250907133731-34b10582faa4

$ mise ls-remote <same> 1>/dev/null
go: module github.com/davidrjenni/reftools/cmd/fillswitch: no matching versions for query "latest"
go: module github.com/davidrjenni/reftools/cmd: no matching versions for query "latest"

Note this is a valid setup producing that noise: _list_remote_versions walks the package path and its parents, so misses are the normal path to a hit, not a fault.

Cause

Three go list calls used duct's .read(), which captures stdout and inherits stderr. mise's own per-candidate message was already demoted to debug!, so the subprocess output was the only thing still reaching the terminal.

The change

Those three calls now use crate::cmd::cmd_read_async, which already exists for exactly this shape — its doc comment says to use it "for backends that pass a full env from dependency_env()", which is what go_list_env() builds. gem.rs is the existing caller.

It maps onto the duct call one-for-one — env_clear().envs(env) for .full_env(), same trailing-newline trim — with two differences that matter here: stderr is piped rather than inherited, and a non-zero exit produces an error whose message carries that stderr. Since the call sites already route their failures into debug!, go's explanation lands behind --verbose instead of on stdout, which is what the issue asks for.

The one place it can still surface at default verbosity is the existing summary warn! in _list_remote_versions, which fires only when every candidate failed — a genuine error where go's reason is the useful part.

Scope

  • go install is untouched. That path uses CmdLineRunner and its output is something the user wants to see.
  • No new setting or flag, so there is no generated-file churn — the diff is src/backend/go.rs plus one e2e assertion.
  • Trade-off worth flagging: stderr from a successful go list is now dropped entirely rather than debug-logged. In practice that is download-progress chatter. If you would rather keep it at debug level, that is a small addition, but it means not reusing the shared helper.
  • Secondary effect: .read() is blocking and was being called from async fn, so the run_with_timeout_async wrapper around _list_remote_versions could not actually interrupt it. cmd_read_async uses tokio::process. I have not measured any speed difference and am not claiming one.

Tests

e2e/backend/test_go_install already exercises the parent-path walk under GOPROXY=direct. Added an assert_not_contains for "go: module" against that same command.

It is placed before the existing assert_matches on purpose: mise caches resolved versions to disk, so running it second would skip go entirely and the assertion would pass without testing anything.

The match string avoids a false positive on mise's own go:github.com/... output, which has no space after the colon.

No unit tests — all three call sites are a go invocation with no separable pure logic.

Summary by CodeRabbit

  • Bug Fixes
    • Direct installation of Go packages no longer displays go list module-walk errors in the default output.
    • Go package metadata lookups now handle non-critical errors more gracefully while continuing with available information.
    • Latest-version resolution provides clearer error context when it cannot determine a version.
    • Added automated coverage to verify clean installation output and reliable version handling.

Version resolution falls back to `go list` when GOPROXY=direct, and the
module-path walk tries a package's parents before it finds the module. Every
miss made `go` write a complaint to stderr, and duct's `.read()` captures only
stdout — so a valid setup printed those lines while mise's own per-candidate
message was already behind `debug!`.

Route the three `go list` calls through `crate::cmd::cmd_read_async`, which
pipes stderr and folds it into the error. The call sites already log their
failures at debug, so go's output now appears under `--verbose` instead.
@coderabbitai

coderabbitai Bot commented Aug 9, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The Go backend now performs module metadata queries asynchronously, logs recoverable query failures at debug level, and preserves contextual errors for latest-version lookup. The direct-installation end-to-end test verifies that default output excludes go: module errors.

Changes

Go module query handling

Layer / File(s) Summary
Asynchronous metadata queries
src/backend/go.rs
Module version and metadata lookups use cmd_read_async. Recoverable failures log debug diagnostics and retain best-effort fallback behavior.
Direct installation output validation
e2e/backend/test_go_install
The test checks that direct-mode installation output does not contain go: module errors before version resolution assertions.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: jdx, risu729

Poem

A rabbit checks the Go path bright,
Async commands hop through the night.
Debug crumbs mark errors small,
Clean install logs greet us all.
“No module noise!” we cheer in delight.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: suppressing go list diagnostics from default output.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@JamBalaya56562
JamBalaya56562 marked this pull request as ready for review August 9, 2026 23:34
@greptile-apps

greptile-apps Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR moves three Go module-resolution commands to the asynchronous command helper so routine go list diagnostics are captured instead of leaking into default output.

  • Preserves full dependency-environment replacement and successful stdout parsing.
  • Routes nonzero-exit stderr through existing debug/error paths.
  • Adds isolated end-to-end coverage for clean output during direct-proxy parent-path resolution.

Confidence Score: 5/5

The PR appears safe to merge with no actionable correctness or security defects identified.

The helper preserves the prior full-environment, argument, exit-status, trimming, and stdout behavior needed by Go resolution while intentionally capturing stderr, and the isolated e2e test verifies both clean output and successful pseudo-version resolution.

Important Files Changed

Filename Overview
src/backend/go.rs Replaces blocking duct reads with the compatible asynchronous helper while preserving resolution fallbacks and capturing subprocess stderr.
e2e/backend/test_go_install Adds a correctly ordered negative-output assertion whose command success and resolved pseudo-version are independently validated.

Reviews (1): Last reviewed commit: "fix(go): keep go list diagnostics out of..." | Re-trigger Greptile

@jdx
jdx merged commit 965ba46 into jdx:main Aug 9, 2026
30 checks passed
@JamBalaya56562
JamBalaya56562 deleted the fix/go-list-stderr-capture branch August 9, 2026 23:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants