Skip to content

impl: relax json syntax rules for deserialization #165

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

fioan89
Copy link
Collaborator

@fioan89 fioan89 commented Jul 28, 2025

For some clients, workspace polling fails due to the following error:

com.squareup.moshi.JsonEncodingException: Use JsonReader.setLenient(true) to accept malformed JSON at path $

I haven’t been able to reproduce this issue, even using the same version deployed at the client (2.20.2). This change is an attempt to relax the JSON parsing rules by enabling lenient mode, in the hope that it will resolve the issue on the client side. On top of it I've add error logging for malformed JSON responses in Coder REST API calls by wrapping Moshi converters in our own custom converter which logs raw response body when JSON parsing fails. It helps debugging
malformed JSON during workspace polling by logging full response content, content type, and error details when a exception during marshalling occurs.

I tried a couple of approaches, unfortunately by the time the exception is raised the response body has already been consumed by Moshi's converter, so you can't read it again. The interceptors are also not really a viable option, they are called before the converters which means:

  • we don't know if the response body is in the correct form or not. This is problematic because it means for every rest call we have to read the body twice (interceptor and by moshi converter)
  • we also have to save the intercepted body and store it until we have an exception from moshi, in which case it will have to be logged.

This approach only logs on conversion failures, and the only performance impact on successful responses is the fact that we convert the response body byte stream to a string representation that can later be printed, and then again back to a byte stream by the moshi converter.

For some clients, workspace polling fails due to the following error:

```
com.squareup.moshi.JsonEncodingException: Use JsonReader.setLenient(true) to accept malformed JSON at path $
```

I haven’t been able to reproduce this issue, even using the same version deployed at the
client (2.20.2). This change is an attempt to relax the JSON parsing rules by enabling
lenient mode, in the hope that it will resolve the issue on the client side.
Copy link
Member

@matifali matifali left a comment

Choose a reason for hiding this comment

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

LGTM. Does being lineant here increase the bug risk?

@fioan89
Copy link
Collaborator Author

fioan89 commented Jul 29, 2025

In theory it should decrease the risk but I can provide any guarantee until I am able to fully understand why the response is malformed/different.

@code-asher
Copy link
Member

My initial impression is that this would only hide some other bug. Maybe a good first step would be to see if we can improve the error message? Like if we could log the request path and response.

@fioan89
Copy link
Collaborator Author

fioan89 commented Jul 30, 2025

Maybe a good first step would be to see if we can improve the error message? Like if we could log the request path and response.

This is what I'm trying to figure out in between other priorities. Unfortunately by the time the exception is raised the response body has already been consumed by Moshi's converter, so you can't read it again. The interceptors are also not really a viable option IMHO, they are called before the converters which means:

  • we don't know if the response body is in the correct form or not. This is problematic because it means for every rest call we have to read the body twice (interceptor and by moshi converter)
  • we also have to save the intercepted body and store it until we have an exception from moshi, in which case it will have to be logged.

Right now I'm playing with custom moshi converters and converter factories. From the docs it looks like it can be done, but I might have to manually write a lot of boilerplate hidden in moshi's factories.

What are your thoughts on this @code-asher ?

@code-asher
Copy link
Member

code-asher commented Jul 31, 2025

Would it be possible to use HttpLoggingInterceptor as an interceptor on the client (with logging level set to BODY)? Maybe we can have a debug-level log flag or something and when it is on we use that interceptor to log all http requests or something like that. Then folks having this issue can turn it on and report back when it happens again.

That is, assuming the interceptor works the way I hope it does 🤞

…I calls

Wraps Moshi converter to log raw response body when JSON parsing fails. It helps debug
malformed JSON during workspace polling by logging full response content, content type, and
error details when a exception during marshalling occurs.

A couple of approaches were tried, unfortunately by the time the exception is raised the
response body has already been consumed by Moshi's converter, so you can't read it again.
The interceptors are also not really a viable option, they are called before the converters which means:

- we don't know if the response body is in the correct form or not. This is problematic
because it means for every rest call we have to read the body twice (interceptor and by
moshi converter)
- we also have to save the intercepted body and store it until we have an exception from
moshi, in which case it will have to be logged.

This approach only logs on conversion failures, and the only performance impact on successful
responses is the fact that we convert the response body byte stream to a string representation
that can later be printed, and then again back to a byte stream by the moshi converter.
@fioan89 fioan89 marked this pull request as ready for review July 31, 2025 22:22
@fioan89 fioan89 requested a review from matifali July 31, 2025 22:22
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.

3 participants