Nvim-lspconfig: Can't get graphql LSP working

I’m struggling to get the graphql LSP working. I’ve followed the instructions and have

  • npm install -g graphql-language-service-cli
  • Enabled the LSP in my nvim config just like my other (working) LSP servers: lspconfig.graphql.setup {}
  • Installed the graphql package in my project
  • Created a graphql.config.js in my project

I’m following the GraphQL Apollo Tutorial here, so my project is very simple. The schema file is in src/schema.gql.

So the graphql.config.js only contains:

module.exports = {
  schema: "./src/schema.gql"
}

When I edit schema.gql and check LspInfo it tells me:

0 client(s) attached to this buffer:

Other clients that match the filetype: graphql

Config: graphql
filetypes: graphql, typescriptreact, javascriptreact
root directory: /home/repos/local/graphql-tutorial-hackernews
cmd: graphql-lsp server -m stream
cmd is executable: true
autostart: true
custom handlers:

So the server gets started and root dir is fine but it is not attached to the buffer.

I’ve checked the LSP debug log and see:

[DEBUG][2022-06-02 09:54:23] .../vim/lsp/rpc.lua:347	"rpc.send"	{  id = 1,  jsonrpc = "2.0",  method = "initialize",  params = {    capabilities = {      callHierarchy = {        dynamicRegistration = false      },      textDocument = {        codeAction = {          codeActionLiteralSupport = {            codeActionKind = {              valueSet = { "", "Empty", "QuickFix", "Refactor", "RefactorExtract", "RefactorInline", "RefactorRewrite", "Source", "SourceOrganizeImports", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" }            }          },          dataSupport = true,          dynamicRegistration = false,          resolveSupport = {            properties = { "edit" }          }        },        completion = {          completionItem = {            commitCharactersSupport = true,            deprecatedSupport = true,            documentationFormat = { "markdown", "plaintext" },            insertReplaceSupport = true,            labelDetailsSupport = true,            preselectSupport = true,            resolveSupport = {              properties = { "documentation", "detail", "additionalTextEdits" }            },            snippetSupport = true,            tagSupport = {              valueSet = { 1 }            }          },          completionItemKind = {            valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 }          },          contextSupport = false,          dynamicRegistration = false        },        declaration = {          linkSupport = true        },        definition = {          linkSupport = true        },        documentHighlight = {          dynamicRegistration = false        },        documentSymbol = {          dynamicRegistration = false,          hierarchicalDocumentSymbolSupport = true,          symbolKind = {            valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 }          }        },        hover = {          contentFormat = { "markdown", "plaintext" },          dynamicRegistration = false        },        implementation = {          linkSupport = true        },        publishDiagnostics = {          relatedInformation = true,          tagSupport = {            valueSet = { 1, 2 }          }        },        references = {          dynamicRegistration = false        },        rename = {          dynamicRegistration = false,          prepareSupport = true        },        signatureHelp = {          dynamicRegistration = false,          signatureInformation = {            activeParameterSupport = true,            documentationFormat = { "markdown", "plaintext" },            parameterInformation = {              labelOffsetSupport = true            }          }        },        synchronization = {          didSave = true,          dynamicRegistration = false,          willSave = false,          willSaveWaitUntil = false        },        typeDefinition = {          linkSupport = true        }      },      window = {        showDocument = {          support = false        },        showMessage = {          messageActionItem = {            additionalPropertiesSupport = false          }        },        workDoneProgress = true      },      workspace = {        applyEdit = true,        configuration = true,        symbol = {          dynamicRegistration = false,          hierarchicalWorkspaceSymbolSupport = true,          symbolKind = {            valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 }          }        },        workspaceEdit = {          resourceOperations = { "rename", "create", "delete" }        },        workspaceFolders = true      }    },    clientInfo = {      name = "Neovim",      version = "0.7.0"    },    initializationOptions = vim.empty_dict(),    processId = 680034,    rootPath = "/home/repos/local/graphql-tutorial-hackernews",    rootUri = "file:///home/repos/local/graphql-tutorial-hackernews",    trace = "off",    workspaceFolders = { {        name = "/home/repos/local/graphql-tutorial-hackernews",        uri = "file:///home/repos/local/graphql-tutorial-hackernews"      } }  }}
[ERROR][2022-06-02 09:54:24] .../vim/lsp/rpc.lua:420	"rpc"	"graphql-lsp"	"stderr"	'2.6.2022, 09:54:24 [3] (pid: 680036) graphql-language-service-usage-logs: {"type":"usage","messageType":"initialize"}\n'
[DEBUG][2022-06-02 09:54:24] .../vim/lsp/rpc.lua:454	"rpc.receive"	{  id = 1,  jsonrpc = "2.0",  result = {    capabilities = {      completionProvider = {        resolveProvider = true,        triggerCharacters = { " ", ":", "$", "\n", " ", "(", "@" }      },      definitionProvider = true,      documentSymbolProvider = true,      hoverProvider = true,      textDocumentSync = 1,      workspace = {        workspaceFolders = {          changeNotifications = true,          supported = true        }      },      workspaceSymbolProvider = true    }  }}
[DEBUG][2022-06-02 09:54:24] .../vim/lsp/rpc.lua:347	"rpc.send"	{  jsonrpc = "2.0",  method = "initialized",  params = vim.empty_dict()}
[DEBUG][2022-06-02 09:54:24] .../lua/vim/lsp.lua:982	"LSP[graphql]"	"server_capabilities"	{  completionProvider = {    resolveProvider = true,    triggerCharacters = { " ", ":", "$", "\n", " ", "(", "@" }  },  definitionProvider = true,  documentSymbolProvider = true,  hoverProvider = true,  textDocumentSync = 1,  workspace = {    workspaceFolders = {      changeNotifications = true,      supported = true    }  },  workspaceSymbolProvider = true}
[INFO][2022-06-02 09:54:24] .../lua/vim/lsp.lua:983	"LSP[graphql]"	"initialized"	{  resolved_capabilities = {    call_hierarchy = false,    code_action = false,    code_lens = false,    code_lens_resolve = false,    completion = true,    declaration = false,    document_formatting = false,    document_highlight = false,    document_range_formatting = false,    document_symbol = true,    execute_command = false,    find_references = false,    goto_definition = true,    hover = true,    implementation = false,    rename = false,    signature_help = false,    signature_help_trigger_characters = {},    text_document_did_change = 1,    text_document_open_close = true,    text_document_save = true,    text_document_save_include_text = false,    text_document_will_save = false,    text_document_will_save_wait_until = false,    type_definition = false,    workspace_folder_properties = {      changeNotifications = true,      supported = true    },    workspace_symbol = true  }}
[DEBUG][2022-06-02 09:54:24] .../vim/lsp/rpc.lua:347	"rpc.send"	{  jsonrpc = "2.0",  method = "textDocument/didOpen",  params = {    textDocument = {      languageId = "graphql",      text = "type Query {\n  info: String!\n  feed: [Link!]!\n}\n\ntype Mutation {\n  post(url: String!, description: String!): Link!,\n  signup(email: String!, password: String!, name: String!): AuthPayload\n  login(email: String!, password: String!): AuthPayload\n}\n\ntype Link {\n  id: ID!\n  description: String!\n  url: String!\n  postedBy: User\n}\n\ntype AuthPayload {\n  token: String\n  user: User\n}\n\ntype User {\n  id: ID!\n  name: String!\n  email: String!\n  links: [Link!]!\n}\n\ntype Subscription {\n  newLink: Link\n}\n",      uri = "file:///home/repos/local/graphql-tutorial-hackernews/src/schema.gql",      version = 0    }  }}

So there’s an ERROR message but I can’t really make sense of it.

At this point I’m stuck as the config LGTM but it still doesn’t connect.

Any ideas what else I could try?

Hmm, is no one using graphql with neovim? Or is there a better place to ask these kind of questions?

I do use it, but I just installed it globally and it kinda works

Thanks. This is weird. I really tried with the most simple setup and the LSP server just won’t attach. Do you have any special entries in your graphql.config.js? Could you maybe do a quick test on a fresh project?

It would really help if neovim would give a little more details with :LspInfo when a LSP server was started but not attached. What does that even mean?

Probably this is the problem? You have .js file, but server only attaches to these three filetypes.

You might want to pass a table to the setup function and add javascript to it.
See default options

Not really. See my post above, I try to edit schema.gql and filetype is also correctly detected as graphql.

Do you have/know a fresh project/template I can use ?

A simple project should be easy to setup:

mkdir demo
cd demo
npm init -y
npm install --save graphql
echo "schema: 'schema.gql'" > .graphqlrc
nvim schema.gql

Then check with :LspInfo whether the LSP server is connected. In my case it’s not.

Does this work for you? If not, maybe I’m missing some important config in the .graphqlrc? I also tried to add documents: '*.gql' to the config but no difference.

Note that it should not matter if we use .graphqlrc or graphql.config.js (see here). Both don’t work for me anyway.

[Edit: Added missing npm init -y]

Nope, it doesn’t work:

Maybe I was happy enough with just higlighting

In ts files it is not attaching either (but it is available):

And some errors:

Ok, thanks for trying and the feedback. I still wonder if anyone got a working setup.

Maybe I should open a neovim issue. But then again I have the strong feeling I’m missing something obvious.