Skip to content

Handle unknown diagnostic tags gracefully - #2847

Merged
jwortmann merged 2 commits into
sublimelsp:mainfrom
jwortmann:diagnostic-tags
Apr 5, 2026
Merged

jwortmann merged 2 commits into
sublimelsp:mainfrom
jwortmann:diagnostic-tags

Conversation

@jwortmann

@jwortmann jwortmann commented Apr 3, 2026 •

Copy link
Copy Markdown
Member

This fixes a runtime error when processing diagnostics with unknown DiagnosticTag values: #2846 (seems like it's already fixed in the server now)

I think that the server should not send values for the tags property that are outside of the predefined DiagnosticTag value range - in particular we send our supported tags (which consist of all the predefined tags) in the initialize params:

LSP/plugin/core/sessions.py

Lines 473 to 474 in 40c9fe3

"tagSupport": {
"valueSet": diagnostic_tag_value_set

But it's better to not crash on unknown tags:
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#publishDiagnosticsClientCapabilities

    /**
	 * Client supports the tag property to provide meta data about a diagnostic.
	 * Clients supporting tags have to handle unknown tags gracefully.
	 *
	 * @since 3.15.0
	 */
	tagSupport?: {
		/**
		 * The tags supported by the client.
		 */
		valueSet: DiagnosticTag[];
	};

I've also cleaned up the get_initialize_params function a bit and got rid of some casts (the enum members are converted to values automatically when sent as JSON).

Instead of including all possible values from the DiagnosticTag enum as supported tags, it's better to list our supported tags manually. This is more future proof in case new tags are added into the DiagnosticTag enum from the specs later (because we need to have a region scope defined for each of the tag values).

@rchl

rchl commented Apr 5, 2026 •

Copy link
Copy Markdown
Member

This change has implications for the log panel but if that's the only thing then I'm fine with that.

Screenshot 2026-04-05 at 19 43 45

(I kind of recall that in the past we had the same "issue" with the log panel and it was addressed but not 100% sure)

@jwortmann

Copy link
Copy Markdown
Member Author

Yes, I remember I added some of these cast and .value access for enum members in the past, so that it is displayed nicely in the panel.

Perhaps the best would be if we could use the actual JSON in the panel directly, instead of the converted Python?

@rchl

rchl commented Apr 5, 2026 •

Copy link
Copy Markdown
Member

Perhaps the best would be if we could use the actual JSON in the panel directly, instead of the converted Python?

Technically it's already converted to python since it needs to be processed by LSP but I agree that showing JSON would be more correct since LSP protocol uses JSON.

Back in the day the argument against showing JSON was that it would require extra processing power. And that's true - some big completion responses can take quite a bit of time to parse but I suppose it would be OK if we'd do that lazily (only when panel is opened).

@rchl rchl left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If we want to show JSON in the lsp log panel then it can be done separately.

@jwortmann

Copy link
Copy Markdown
Member Author

Technically it's already converted to python since it needs to be processed by LSP but I agree that showing JSON would be more correct since LSP protocol uses JSON.

I'm not very familiar with the code to handle the JSONRPC messages, but I assume the message.decode('utf-8') should be a JSON string? Although we don't seem to do that if orjson is available.

@staticmethod
def _decode(message: bytes) -> dict[str, Any]:
if orjson:
return orjson.loads(message)
return json.loads(message.decode('utf-8'))

@jwortmann
jwortmann merged commit 529c092 into sublimelsp:main Apr 5, 2026
14 of 16 checks passed
@jwortmann
jwortmann deleted the diagnostic-tags branch April 5, 2026 18:50
@rchl

rchl commented Apr 5, 2026

Copy link
Copy Markdown
Member

Technically it's already converted to python since it needs to be processed by LSP but I agree that showing JSON would be more correct since LSP protocol uses JSON.

I'm not very familiar with the code to handle the JSONRPC messages, but I assume the message.decode('utf-8') should be a JSON string? Although we don't seem to do that if orjson is available.

@staticmethod
def _decode(message: bytes) -> dict[str, Any]:
if orjson:
return orjson.loads(message)
return json.loads(message.decode('utf-8'))

Right, we could hook up to those places where we do serialization (for outgoing) and parsing (for incoming) but that would require a bit of refactoring.

Also for incoming we would ideally re-format (parse and serialize again) to have consistent formatting but perhaps that's not essential.

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