LSP: .lsp.json `settings` never reach the language server (workspace/configuration handler returns null)

Resolved 💬 2 comments Opened Jun 23, 2026 by masaki4680 Closed Jun 27, 2026

Summary

A plugin's .lsp.json settings field never reaches the language server, so server-side configuration (e.g. intelephense's environment.phpVersion) is silently ignored and the server falls back to its built-in defaults.

The LSP integration itself works (document symbols, hover, references, and diagnostics all function), but there appears to be no working channel to deliver per-server configuration.

Environment

  • Claude Code: 2.1.186 (Linux / WSL2)
  • Plugin: php-lsp@claude-plugins-official with a manually-added .lsp.json (the shipped plugin omits it — see anthropics/claude-plugins-official#444)
  • Language server: intelephense 1.18.5

.lsp.json

{
  "php": {
    "command": "intelephense",
    "args": ["--stdio"],
    "extensionToLanguage": { ".php": "php", ".phtml": "php", ".ctp": "php" },
    "settings": {
      "intelephense": {
        "environment": { "phpVersion": "7.2.34" }
      }
    }
  }
}

Expected

intelephense analyzes code targeting PHP 7.2.34.

Actual

intelephense analyzes targeting its default PHP 8.5. Opening a .php file containing $str{0} (curly-brace string offset — valid in 7.2, removed in 8.0) yields:

Array or string offset access with curly braces deprecated in PHP 7.4. Targeting PHP 8.5. [P1034] (intelephense)

The Targeting PHP 8.5 text confirms the phpVersion setting from .lsp.json was never applied.

Root cause (from inspecting the 2.1.186 binary)

intelephense receives environment.phpVersion only through LSP configuration (it does not read it from initializationOptions — only storagePath/globalStoragePath/clearCache/licenceKey are read there). Both LSP configuration channels appear broken:

  1. Pull (workspace/configuration) — the client advertises the capability as disabled:

``
workspace:{configuration:!1, workspaceFolders:!1}
`
…yet still registers a handler that returns
null for every requested item:
`js
C.onRequest("workspace/configuration", (k) => (
T(
LSP: Received workspace/configuration request from ${S}),
k.items.map(() => null)
))
`
So any server that pulls config gets
null` for every section.

  1. Push (workspace/didChangeConfiguration) — the .lsp.json schema documents settings as "Settings passed to the server via workspace/didChangeConfiguration", but the value never takes effect (intelephense still targets its default version after init and after re-parsing the document).

Net effect: the settings field in .lsp.json is effectively a no-op for any server that needs configuration to function correctly.

Repro

  1. Install php-lsp@claude-plugins-official and add the .lsp.json above.
  2. Restart Claude Code (LSP/plugin config is read at process startup).
  3. Open a .php file containing:

``php
<?php
$str = 'hello';
echo $str{0};
``

  1. Observe the diagnostic reports Targeting PHP 8.5 instead of honoring phpVersion: "7.2.34".

Suggestion

Either implement the workspace/configuration pull handler to return the matching section from .lsp.json settings (e.g. return settings["intelephense"] for section: "intelephense"), or ensure the didChangeConfiguration push delivers settings in the shape servers expect. As-is, server configuration via .lsp.json settings cannot be relied upon.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗