Skip to content

Route deprecated-alias warnings and writer errors to stderr - #77

Merged
imanimanyara merged 1 commit into
mainfrom
fix/alias-warning-stderr
Oct 7, 2026
Merged

imanimanyara merged 1 commit into
mainfrom
fix/alias-warning-stderr

Conversation

@imanimanyara

Copy link
Copy Markdown
Member

What

WarnsOnDeprecatedAlias is documented to print its warning on stderr, so piped output is unchanged. It printed on stdout. ConsoleWriter's error(), danger() and toStderr() had the same defect whenever the writer came from a command.

Root cause

Illuminate\Console\Command::run() wraps the output it receives in an Illuminate\Console\OutputStyle before Symfony calls initialize() or handle(). OutputStyle does not implement ConsoleOutputInterface, so $output instanceof ConsoleOutputInterface was false for every output a command sees, and both call sites fell back to stdout. Found in review of laranail/package-scaffolder#28: running module:list against an output with a separate error stream put Deprecated: [module:list] is a deprecated alias... on the first line of stdout, with stderr empty.

Fix

  • New Tools\Support\ErrorOutput::of() (internal): unwraps an OutputStyle with getOutput(), then returns getErrorOutput() when the inner output is a ConsoleOutputInterface, otherwise the original output.
  • WarnsOnDeprecatedAlias::initialize() and ConsoleWriter (status() and stream()) resolve stderr through it.
  • An output with no error stream (BufferedOutput, as Artisan::call() uses) gets the line as before, so Artisan::output() still contains the warning.

Behaviour change

On a real terminal the alias warning and ConsoleWriter errors move from stdout to stderr, which is what the docs already said. Recorded under [Unreleased] / Fixed in the CHANGELOG.

Tests

tests/Tools/Unit/Commands/StderrRoutingTest.php runs commands through the real Command::run() path with an output that keeps stdout and stderr in separate streams:

  • a deprecated alias puts the warning on stderr and only handled on stdout;
  • the alias's stdout is identical to the canonical name's;
  • a command's consoleWriter()->error() and ->toStderr() reach stderr.

All three fail on the previous code (the warning and error lines appear on stdout) and pass with this change. Local: pest 561 passed, phpstan no errors, rector and pint clean.

Illuminate\Console\Command::run() wraps the terminal output in an
OutputStyle before initialize() and handle() see it, and OutputStyle is
not a ConsoleOutputInterface. The instanceof checks in
WarnsOnDeprecatedAlias and ConsoleWriter therefore never matched inside
a command, so the alias warning became the first line of stdout and
ConsoleWriter error(), danger() and toStderr() wrote to stdout too.

Both now resolve the error stream through Tools\Support\ErrorOutput,
which unwraps the style first. Outputs without an error stream, such as
the buffer Artisan::call() uses, are unchanged.

The new test drives the real Command::run() path with an output that
keeps stdout and stderr apart; it fails on the previous code.
Copilot AI balanced review requested due to automatic review settings October 7, 2026 12:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@imanimanyara
imanimanyara merged commit 33ca8a8 into main Oct 7, 2026
12 checks passed
@imanimanyara
imanimanyara deleted the fix/alias-warning-stderr branch October 7, 2026 13:12
imanimanyara added a commit to laranail/package-scaffolder that referenced this pull request Oct 7, 2026
)

laranail/console#77 makes the shared WarnsOnDeprecatedAlias see through
Laravel's OutputStyle, so on a terminal the bare-alias warning goes to
stderr rather than leading stdout. The installation guide and the
Unreleased CHANGELOG entry now describe that, and say v0.1.5 still puts
the line on stdout.

DeprecatedAliasTest no longer leaves the stream open: it pins stderr when
the installed console carries the fix and stdout when it does not, so it
asserts the right stream on both sides of the upgrade and fails if the
fixed release regresses.
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