Skip to content

lsp_diagnostics silently returns empty results for strict LSP servers due to null fields in textDocument/diagnostic pull request #63

@null-axiom

Description

@null-axiom

What happened?

When lsp_diagnostics is called for a file handled by an LSP server that supports the 3.17 pull model (e.g., tsgo, the TypeScript-Go LSP), AFT sends a textDocument/diagnostic request with "identifier": null and "previousResultId": null in the params body.

Strict LSP servers reject this with InvalidParams (-32602) because JSON Schema defines those fields as string? (string-or-absent), not string-or-null. This triggers AFT's recoverable_pull_rejection path (status: pull_rejected_push_fallback), which then waits for push diagnostics that never arrive from pull-only servers. The result is empty diagnostics with complete: false and the server stuck in pending_servers with no type errors surface despite clear violations in the file.

Root cause: The upstream lsp-types crate (v0.97) is missing #[serde(skip_serializing_if = "Option::is_none")] on the identifier and previous_result_id fields of DocumentDiagnosticParams (and the identifier field of WorkspaceDiagnosticParams). Rust Option::None gets serialized as JSON null instead of the field being omitted entirely.

Impact: Affects any LSP server that strictly validates against the LSP spec schema. Currently reproducible with tsgo (TypeScript-Go), and potentially other strict LSP 3.17 servers.
Reproduction Steps:

  1. Configure tsgo as an LSP server in aft.jsonc:
"servers": {
  "tsgo": {
    "extensions": [".ts", ".tsx", ".js"],
    "binary": "tsgo",
    "args": ["--lsp", "--stdio"]
  }
}
  1. Create a .ts file with a type error: const x: number = "hello";
  2. Run lsp_diagnostics on the file with wait_ms > 0
  3. Observe status: "pull_rejected_push_fallback", complete: false, diagnostics: []

Diagnostics

Plugin version

No response

AFT binary version

No response

Platform

No response

Log output (optional)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions