Skip to content

Conversation

@pyq
Copy link
Contributor

@pyq pyq commented Sep 4, 2025

User description

The console object in cli.py was created without stderr=True, causing unhandled exception tracebacks to be printed to stdout instead of stderr. This fix ensures proper error stream routing by configuring the console to use stderr, matching the behavior of the logging system.


PR Type

Bug fix


Description

  • Configure CLI console to route error tracebacks to stderr

  • Fix improper error stream routing in command-line interface


Diagram Walkthrough

flowchart LR
  A["CLI Console Creation"] --> B["Add stderr=True parameter"] --> C["Error tracebacks route to stderr"]
Loading

File Walkthrough

Relevant files
Bug fix
cli.py
Configure console for stderr error routing                             

src/mcpm/cli.py

  • Modified Console initialization to include stderr=True parameter
  • Ensures error tracebacks are properly routed to stderr stream
+1/-1     

Summary by CodeRabbit

  • New Features

    • None.
  • Bug Fixes

    • CLI diagnostics, rich tracebacks, and error banners now print to standard error instead of standard output, keeping regular command output clean. This improves piping, redirection, and automation reliability and ensures error output is separated from normal program output.
  • Documentation

    • None.
  • Refactor

    • None.
  • Tests

    • None.
  • Chores

    • None.
  • Revert

    • None.

Copilot AI review requested due to automatic review settings September 4, 2025 14:27
@coderabbitai
Copy link

coderabbitai bot commented Sep 4, 2025

Walkthrough

Created a new module-level err_console (Rich Console with stderr=True) in src/mcpm/cli.py, installed Rich's global traceback handler to use it, and redirected all exception/error output to err_console; main command registration and setup_logging() call remain unchanged.

Changes

Cohort / File(s) Summary
CLI stderr console & traceback routing
src/mcpm/cli.py
Added err_console: Console configured with stderr=True; imported and invoked install_rich_traceback to route tracebacks (with locals) to err_console; replaced prior exception/error output sinks to use err_console while leaving console, setup_logging() and command flow intact.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI entry
    participant ConsoleOut as console (stdout)
    participant ErrConsole as err_console (stderr)
    participant RichTB as Rich traceback handler

    CLI->>ConsoleOut: normal output (prints, progress)
    CLI->>RichTB: install_rich_traceback(target=ErrConsole)
    Note over RichTB,ErrConsole: RichTB configured to send tracebacks to ErrConsole
    CLI->>ErrConsole: exception occurs -> RichTB renders traceback to ErrConsole
    CLI->>ErrConsole: prints error banner and GitHub guidance
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

I nudge a stream and send errors astray,
To stderr they hop, where they loudly stay.
Stdout keeps carrots neat in a row,
While tracebacks thump where bright debug lights glow.
— a rabbit, piping logs on the go 🐇

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/console-stderr-routing

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@qodo-merge-pro
Copy link
Contributor

qodo-merge-pro bot commented Sep 4, 2025

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 1 🔵⚪⚪⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Behavior Change

Switching the console to stderr may affect any tooling or scripts parsing stdout; verify no commands rely on stdout for error messages and that regular non-error output still goes to stdout.

console = Console(stderr=True)
client_config_manager = ClientConfigManager()

@qodo-merge-pro
Copy link
Contributor

qodo-merge-pro bot commented Sep 4, 2025

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Use separate stdout and stderr consoles

Routing the main console to stderr sends all normal CLI output to stderr,
breaking stdout pipelines. Keep a stdout console for regular output and
introduce a dedicated stderr console for tracebacks. Update exception/traceback
printing to use the stderr console.

src/mcpm/cli.py [34]

-console = Console(stderr=True)
+console = Console()
+error_console = Console(stderr=True)
  • Apply / Chat
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies that routing all console output to stderr breaks standard CLI behavior, such as piping. Creating a separate console for stderr is the correct approach to handle errors without affecting standard output.

High
  • Update

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/mcpm/cli.py (2)

56-61: Send tracebacks and error messages to the stderr console.

With a dedicated stderr console, print exceptions and error text there.

-            console.print(Traceback(show_locals=True))
-            console.print("[bold red]An unexpected error occurred.[/bold red]")
-            console.print(
+            err_console.print(Traceback(show_locals=True))
+            err_console.print("[bold red]An unexpected error occurred.[/bold red]")
+            err_console.print(
                 "Please report this issue on our GitHub repository: "
                 "[link=https://github.com/pathintegral-institute/mcpm.sh/issues]https://github.com/pathintegral-institute/mcpm.sh/issues[/link]"
             )

52-63: Exit non‑zero on unhandled exceptions.

The decorator swallows exceptions and exits 0, which breaks scripting/automation.

Within the except block:

             err_console.print(
                 "Please report this issue on our GitHub repository: "
                 "[link=https://github.com/pathintegral-institute/mcpm.sh/issues]https://github.com/pathintegral-institute/mcpm.sh/issues[/link]"
             )
+            sys.exit(1)

Add at top:

-from typing import Any, Dict
+from typing import Any, Dict
+import sys

Want me to open a quick follow-up PR for this?

🧹 Nitpick comments (1)
src/mcpm/cli.py (1)

5-5: Comment/import order mismatch.

The comment says to import rich-click config “before anything else,” but it’s imported later (Line 32). Either move that import up or adjust the comment.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6d3728f and e7f7efc.

📒 Files selected for processing (1)
  • src/mcpm/cli.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Always format Python code with ruff.

Files:

  • src/mcpm/cli.py

Create separate Console instances for regular CLI output (stdout) and
error handling (stderr). This ensures:
- Logo, help, and normal UI go to stdout (console)
- Error tracebacks and error messages go to stderr (err_console)

Follows Unix conventions for proper stream separation without mixing
normal program output with error diagnostics.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@pyq pyq force-pushed the fix/console-stderr-routing branch from e7f7efc to 7179309 Compare September 4, 2025 14:37
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/mcpm/cli.py (1)

57-63: Unhandled exceptions currently return exit code 0 — re-raise with non-zero.

Catching Exception and not re-raising exits successfully, breaking scripts that rely on non-zero on failure.

Apply:

 except Exception:
     err_console.print(Traceback(show_locals=True))
     err_console.print("[bold red]An unexpected error occurred.[/bold red]")
     err_console.print(
         "Please report this issue on our GitHub repository: "
         "[link=https://github.com/pathintegral-institute/mcpm.sh/issues]https://github.com/pathintegral-institute/mcpm.sh/issues[/link]"
     )
+    raise SystemExit(1)
♻️ Duplicate comments (1)
src/mcpm/cli.py (1)

34-35: Good stdout/stderr split; prior concern addressed.

Using separate Console instances for stdout (console) and stderr (err_console) is the correct fix and avoids polluting stderr with normal UI.

🧹 Nitpick comments (2)
src/mcpm/cli.py (2)

57-59: Avoid leaking locals in tracebacks; gate under debug flag.

Printing locals can expose tokens/paths. Gate it behind an env flag.

Within wrapper:

-    err_console.print(Traceback(show_locals=True))
+    err_console.print(Traceback(show_locals=bool(os.getenv("MCPM_DEBUG"))))

Add import near the top:

import os

57-61: Add a small integration test to assert stderr routing.

Use Click’s CliRunner to ensure traceback text lands in stderr, not stdout.

I can open a follow-up PR with a test like:

from click.testing import CliRunner
from src.mcpm.cli import main

def test_errors_to_stderr(monkeypatch):
    @main.command()
    def boom():
        raise RuntimeError("boom")

    runner = CliRunner(mix_stderr=False)
    result = runner.invoke(main, ["boom"])
    assert result.exit_code != 0
    assert "Traceback" in result.stderr
    assert "Traceback" not in result.output
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e7f7efc and 7179309.

📒 Files selected for processing (1)
  • src/mcpm/cli.py (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Always format Python code with ruff.

Files:

  • src/mcpm/cli.py

…rting

Added installation of Rich's global exception handler to route tracebacks to stderr instead of stdout. This change enhances error diagnostics by preventing mixing of normal output with error messages.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/mcpm/cli.py (1)

62-69: Return non-zero on errors and also gate locals here.

  • CLI currently swallows exceptions and exits 0, which breaks scripting/CI.
  • Mirror the debug-guard for locals to prevent accidental data exposure.

Apply:

-            err_console.print(Traceback(show_locals=True))
+            err_console.print(Traceback(show_locals=SHOW_LOCALS))
             err_console.print("[bold red]An unexpected error occurred.[/bold red]")
             err_console.print(
                 "Please report this issue on our GitHub repository: "
                 "[link=https://github.com/pathintegral-institute/mcpm.sh/issues]https://github.com/pathintegral-institute/mcpm.sh/issues[/link]"
             )
+            # Ensure a failing exit code for scripting/CI
+            raise SystemExit(1)
♻️ Duplicate comments (1)
src/mcpm/cli.py (1)

35-36: Good split between stdout and stderr consoles.

This addresses the earlier concern about mixing normal UI with error output. LGTM.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 7179309 and 01aefba.

📒 Files selected for processing (1)
  • src/mcpm/cli.py (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Always format Python code with ruff.

Files:

  • src/mcpm/cli.py
🧬 Code graph analysis (1)
src/mcpm/cli.py (2)
src/mcpm/commands/install.py (1)
  • install (123-448)
src/mcpm/utils/logging_config.py (1)
  • setup_logging (12-44)
🔇 Additional comments (1)
src/mcpm/cli.py (1)

10-10: Import alias for Rich traceback installer is appropriate.

Keeps call sites explicit and readable. LGTM.

@pyq pyq requested a review from JoJoJoJoJoJoJo September 5, 2025 01:31
@pyq pyq merged commit 38b04ff into main Sep 5, 2025
8 checks passed
@pyq pyq deleted the fix/console-stderr-routing branch September 5, 2025 03:17
mcpm-semantic-release bot pushed a commit that referenced this pull request Sep 11, 2025
# [2.8.0](v2.7.1...v2.8.0) (2025-09-11)

### Bug Fixes

* separate console streams for proper stdout/stderr routing ([#255](#255)) ([38b04ff](38b04ff))

### Features

* add manifest for hustcc-mcp-mermaid ([#240](#240)) ([793e160](793e160))
@mcpm-semantic-release
Copy link

🎉 This PR is included in version 2.8.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants