Eugleo / magic-racket

The best coding experience for Racket in VS Code
https://marketplace.visualstudio.com/items?itemName=evzen-wybitul.magic-racket
GNU General Public License v3.0
202 stars 28 forks source link

Error: Header must provide a Content-Length property. #77

Closed PappasBrent closed 1 year ago

PappasBrent commented 2 years ago

Environment

Error message

[2022-08-12 11:02:12.925] [exthost] [error] Error: Header must provide a Content-Length property.
    at StreamMessageReader.onData (/home/bpappas/.vscode/extensions/evzen-wybitul.magic-racket-0.6.4/node_modules/vscode-jsonrpc/lib/common/messageReader.js:138:27)
    at Socket.<anonymous> (/home/bpappas/.vscode/extensions/evzen-wybitul.magic-racket-0.6.4/node_modules/vscode-jsonrpc/lib/common/messageReader.js:122:18)
    at Socket.emit (node:events:390:28)
    at addChunk (node:internal/streams/readable:315:12)
    at readableAddChunk (node:internal/streams/readable:289:9)
    at Socket.Readable.push (node:internal/streams/readable:228:10)
    at Pipe.onStreamRead (node:internal/stream_base_commons:199:23)

Additional context

Thank you for this extension. I really like it, but am currently running into the following error. Magic Racket only seems to work for new files. When I reopen a .rkt file, Magic Racket stops working.

Steps to reproduce:

  1. Create a new .rkt file:
    #lang racket
    'test
  2. Save the file and close VS Code.
  3. Reopen VS Code.
  4. Reopen the file (if not already open).
  5. Try to use Magic Racket features (e.g., auto-complete, auto-format).

When I try to use these features, nothing happens. When I check output -> extension host, I see the error message listed above.

I am able to "fix" the issue by turning off the language server, closing VS Code, and restarting the language server; however this is not convenient.

Any help would be appreciated, thank you.

PappasBrent commented 2 years ago

add Ubuntu version

PappasBrent commented 2 years ago

More information: this issue is only occurring when I use #lang pie. For context, Pie is the Racket language associated with the book The Little Typer. This issue does not occur if I use #lang racket. I have not tried it with other #langs.

elmisback commented 1 year ago

On WSL, I am seeing a similar error on the same Ubuntu, VSCode 1.73.0, Racket 8.6, current racket-langserver (?) and Magic Racket version (0.6.4). Code that produces the content-length error + crash for me is:

#lang racket

(require plot/no-gui)
(local-require (only-in plot/no-gui [plot-file plot-file*]))

The error itself (in the developer tools console), shown whenever the file is interacted with:

Error: Header must provide a Content-Length property.
    at StreamMessageReader.onData (vscode-file://vscode-app/home/elm/.vscode-server/extensions/evzen-wybitul.magic-racket-0.6.4/node_modules/vscode-jsonrpc/lib/common/messageReader.js:138:27)
    at Socket.<anonymous> (vscode-file://vscode-app/home/elm/.vscode-server/extensions/evzen-wybitul.magic-racket-0.6.4/node_modules/vscode-jsonrpc/lib/common/messageReader.js:122:18)
    at Socket.emit (node:events:526:28)
    at addChunk (node:internal/streams/readable:315:12)
    at readableAddChunk (node:internal/streams/readable:289:9)
    at Socket.Readable.push (node:internal/streams/readable:228:10)
    at Pipe.onStreamRead (node:internal/stream_base_commons:190:23)

Based on https://github.com/Microsoft/vscode/issues/4869, it seems like this could have something to do with the language server writing to stdout without an appropriate header in some particular case (eg improper output associated with processing something in plot/no-gui (or something to do with local-require) || #lang pie--I'm not a racket expert, though...).

Can we confirm that this is a langserver issue and file the issue there?

It would also be nice if magic-racket could handle the error gracefully instead of crashing.

(https://github.com/jeapostrophe/racket-langserver/issues/76 shows an example of the header and also points at a possible improper content length, but this seems less likely as a cause.)

elmisback commented 1 year ago

I looked into this a bit further by running the extension with a debugger. It seems like the langserver is responding with a message like

Caught exn:
standard-module-name-resolver: contract violation
  expected: module-path?
  given: '(just-space #f (rename plot/no-gui b plot-file))
  context...:
   /home/elm/.local/share/racket/8.6/pkgs/racket-langserver/autocomplete.rkt:106:0: walk-module
   /home/elm/.local/share/racket/8.6/pkgs/racket-langserver/check-syntax.rkt:111:10
   /usr/share/racket/collects/racket/logging.rkt:43:0: with-intercepted-logging
   /home/elm/.local/share/racket/8.6/pkgs/racket-langserver/check-syntax.rkt:77:0: check-syntax
   /usr/share/racket/collects/racket/contract/private/arrow-val-first.rkt:486:18
   /home/elm/.local/share/racket/8.6/pkgs/racket-langserver/text-document.rkt:65:0: did-open!
   /usr/share/racket/collects/racket/contract/private/arrow-val-first.rkt:486:18
   [repeats 1 more time]
   /home/elm/.local/share/racket/8.6/pkgs/racket-langserver/main.rkt:54:2: consume

Caught exn in request "textDocument/documentSymbol"
hash-ref: no value found for key
  key: 'file:///home/elm/temp/tst.rkt
  context...:
   /home/elm/.local/share/racket/8.6/pkgs/racket-langserver/text-document.rkt:405:0: document-symbol
   /usr/share/racket/collects/racket/contract/private/arrow-val-first.rkt:486:18
   /home/elm/.local/share/racket/8.6/pkgs/racket-langserver/methods.rkt:26:0: process-message
   /usr/share/racket/collects/racket/contract/private/arrow-val-first.rkt:486:18
   /home/elm/.local/share/racket/8.6/pkgs/racket-langserver/main.rkt:54:2: consume

Content-Length: 117

{"error":{"code":-32603,"message":"internal error in method \"textDocument/documentSymbol\""},"id":1,"jsonrpc":"2.0"}

The error message appears to cause the header to be missed as I guessed. I don't know what is standard for a language server response, but this seems like incorrect behavior if it's causing an error at the jsonrpc level, so I'll report this over there.

elmisback commented 1 year ago

(Subsequently, proper responses are also messed up because the top of the underlying message passing buffer has been filled with junk and can't be cleared. I'm assuming the language server isn't crashed after hitting the exception, it seems to keep sending responses that look valid for non-janky racket code.)

More information: it looks like these exceptions can't be caught on Magic Racket's side due to the jsonrpc reader not implementing a proper error handler as https://github.com/microsoft/vscode-languageserver-node/issues/870 reports, and a PR for that is waiting since Dec 2021 (https://github.com/microsoft/vscode-languageserver-node/pull/871). So for now it's important to prevent the language server from mixing stderr into the response.

elmisback commented 1 year ago

In case anyone else needs a quick fix for this, I confirmed that running a modified language server with the offending eprintf calls commented out solves the problem. There might be a way to set the error port (basically to redirect stderr I think) when running the server on Magic Racket's side, but I'm not familiar enough with Racket to figure this out.

elmisback commented 1 year ago

Finally figured this out! To cause this error, you need to be using xvfb-run and working on a file that causes an error in the langserver.

It turns out that xvfb-run dumps stderr into stdout (!), and the langserver writes a debugging message to stderr when it can't handle a request (besides also sending a normal error message to Magic Racket on stdout). This is a known Ubuntu bug: https://bugs.launchpad.net/ubuntu/+source/xorg-server/+bug/1059947. The mixed streams break the communication channel after that.

I fixed this by modifying /usr/bin/xvfb-run as suggested here: https://superuser.com/questions/1719253/xvfb-run-redirects-stdout-and-stderr-to-stdout-only. You may want to suggest this for other users who resort to using xvfb-run for running headless.

Eugleo commented 1 year ago

Added a link to this issue in the README, closing. Thanks @elmisback for the detailed investigation and the workaround!