Skip to content

Conversation

@jan-dh
Copy link

@jan-dh jan-dh commented Dec 11, 2025

PHP processes often emit deprecation warnings, notices, or other text before/after JSON LSP messages (especially on PHP 8.4+) — breaking the language server’s JSON protocol causing VSCode to crash (see #69
).

  • Updated exec() in packages/language-server/src/utils/exec.ts to strip all leading non-JSON noise from stdout before resolving.
  • Stdout is now scanned for the first { or [ character, discarding anything before it.
  • stderr is still captured but no longer treated as fatal — logged separately by the caller if needed.
  • API of exec() and isProcessError() unchanged — fully backwards compatible.

⚠️ Haven't been able to test this locally, so take it for a spin first please 🙏


child.on('close', (code) => resolve({ stdout, stderr, code }));
child.on('close', (code) => {
const jsonStart = stdout.search(/[{[]/);
Copy link
Owner

Choose a reason for hiding this comment

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

I don't really want to rely in trying to find [ or { in the stdout. Deprecation notices possibly could use these characters to format their messages, like [Deprecated]. I see that it's not the case but this solution does not seem that robust to me.


In continuation of this comment: #69 (comment)

I was expecting all the warnings go to stderr, and the rest to stdout. Now I see that running php bin/console depends on the user environment (php.ini).

According to the PHP runtime documentation, we can use the ini option display_errors to make the php executable do the expected thing.
https://www.php.net/manual/en/errorfunc.configuration.php#ini.display-errors

Value "stderr" sends the errors to stderr instead of stdout.

And we can pass ini option as an argument to php using -d param:
php -d display_errors=stderr bin/console debug:twig --format json
(src: https://www.php.net/manual/en/features.commandline.options.php)

Now, if we change this:

const result = await exec(this._phpExecutable, [
command,
...args,
], {
cwd: this._workspaceDirectory
});

to this:

const result = await exec(this._phpExecutable, [
    '-d',
    'display_errors=stderr',
    command,
    ...args,
], {
    cwd: this._workspaceDirectory
});

that would hopefully to fix the issue.

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