Monaco JS: Error: Object reference not set to an instance of an object.
palkerecsenyi opened this issue · 2 comments
Environment data
- Language Server version: Commit 4f81ba2, release build
- OS and version: Debian Buster
- Python version: 3.9.1
Expected behaviour
I'm trying to set up Python Language Server to connect to an instance of the Monaco editor running on a website. The server doesn't have the code stored on it, and I'm using monaco-languageclient
to send the user's Python code as an in-memory file. I'd like the frontend Monaco editor to support Python Language Server's LSP functionality.
Actual behaviour
I get the following error message the moment the Monaco editor loads:
Error: Object reference not set to an instance of an object.
Logs
[Info - 16:10:52] Analysis cache path: /root/.cache/Microsoft/Python Language Server
[Info - 16:10:52] Microsoft Python Language Server version 1.0.0.0
[Info - 16:10:52] Workspace root:
[Error - 16:10:54] Request textDocument/codeAction failed.
Error: The task was cancelled.
Error: Object reference not set to an instance of an object.
A request has failed. See the output for more information.
Uncaught Error: Object reference not set to an instance of an object.
There is nothing else logged on the server.
Code Snippet / Additional information
React frontend
import {
CloseAction,
createConnection,
ErrorAction,
MonacoLanguageClient,
MonacoServices,
} from 'monaco-languageclient';
import { listen, MessageConnection } from 'vscode-ws-jsonrpc';
import getEnvVariable from './getEnv';
import { TaskLanguage } from '../types';
function createLanguageClient(connection: MessageConnection) {
return new MonacoLanguageClient({
name: 'lsp.palcode.dev',
clientOptions: {
documentSelector: ['python', 'shell'],
errorHandler: {
error: () => ErrorAction.Continue,
closed: () => CloseAction.DoNotRestart,
}
},
connectionProvider: {
get(errorHandler, closeHandler) {
return Promise.resolve(createConnection(
// @ts-ignore
connection,
errorHandler,
closeHandler,
));
}
}
});
}
type DisposeFunction = () => void;
export default function connectToLanguageServer(
language: TaskLanguage,
): undefined | DisposeFunction {
const lspURL = getEnvVariable('LSP');
if (!lspURL) {
return;
}
try {
MonacoServices.get();
} catch (e) {
// @ts-ignore
MonacoServices.install(require('monaco-editor-core/esm/vs/platform/commands/common/commands').CommandsRegistry);
}
// in this case, language is 'python'
const webSocket = new WebSocket(lspURL + '/' + language);
webSocket.onerror = () => {};
let pingInterval: number;
listen({
webSocket,
onConnection: (connection) => {
const client = createLanguageClient(connection);
const disposable = client.start();
connection.onClose(() => disposable.dispose());
connection.onError(() => {});
pingInterval = window.setInterval(() => {
webSocket.send('ping');
}, 20000);
},
});
return () => {
try {
webSocket.close();
clearInterval(pingInterval);
} catch (e) {}
};
}
Node.JS backend
import * as http from 'http';
import ws from 'ws';
import * as url from 'url';
import * as rpc from 'vscode-ws-jsonrpc';
import * as server from 'vscode-ws-jsonrpc/lib/server';
import * as lsp from 'vscode-languageserver';
function launch(socket: rpc.IWebSocket, command: string, args: string[]) {
const reader = new rpc.WebSocketMessageReader(socket);
const writer = new rpc.WebSocketMessageWriter(socket);
const socketConnection = server.createConnection(reader, writer, () => socket.dispose());
const serverConnection = server.createServerProcess('JSON', command, args);
server.forward(socketConnection, serverConnection, message => {
if (rpc.isRequestMessage(message)) {
if (message.method === lsp.InitializeRequest.type.method) {
const initializeParams = message.params;
initializeParams.processId = process.pid;
}
}
return message;
});
}
const httpServer = http.createServer((req, res) => {
// required for health checks
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('');
res.end();
}).listen(process.env.PORT);
const socketServers: {
[path: string]: ws.Server,
} = {};
const languages = [
{
command: '/opt/python-language-server/output/bin/Release/Microsoft.Python.LanguageServer',
args: [],
path: '/python',
},
{
command: 'bash-language-server',
args: ['start'],
path: '/bash',
},
];
for (const language of languages) {
const socket = new ws.Server({
perMessageDeflate: false,
noServer: true,
});
socket.on('connection', (client) => {
const iWebSocket = {
send: (content: any) => client.send(content),
onMessage: (cb: (message: ws.Data) => void) => client.onmessage = event => {
if (event.data !== 'ping') {
cb(event.data);
}
},
onError: (cb: (message: string) => void) => client.onerror = event => {
if ('message' in event) {
cb(event.message)
}
},
onClose: (cb: (code: number, reason: string) => void) => client.onclose = event => cb(event.code, event.reason),
dispose: () => client.close(),
};
launch(iWebSocket, language.command, language.args);
});
socketServers[language.path] = socket;
}
httpServer.on('upgrade', (request, socket, head) => {
const pathname = url.parse(request.url).pathname;
if (!pathname) {
socket.destroy();
return;
}
const socketServer = socketServers[pathname];
if (!socketServer) {
socket.destroy();
return;
}
socketServer.handleUpgrade(request, socket, head, (ws) => {
socketServer.emit('connection', ws, request);
});
});
Hey @palkerecsenyi , did you find a fix for this issue?
Thank you for the report. This project is no longer active. If you are using the Python language server in VSCode, the language server you are using is Pylance and please the http://github.com/microsoft/pylance-release to report issues.
If you are using Visual Studio, then, please use http://github.com/microsoft/PTVS to report issues.
thank you