diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs
index ac6ae70a..fdff553f 100644
--- a/helix-lsp/src/client.rs
+++ b/helix-lsp/src/client.rs
@@ -583,19 +583,19 @@ impl Client {
 
     // formatting
 
-    pub async fn text_document_formatting(
+    pub fn text_document_formatting(
         &self,
         text_document: lsp::TextDocumentIdentifier,
         options: lsp::FormattingOptions,
         work_done_token: Option<lsp::ProgressToken>,
-    ) -> anyhow::Result<Vec<lsp::TextEdit>> {
+    ) -> Option<impl Future<Output = Result<Vec<lsp::TextEdit>>>> {
         let capabilities = self.capabilities.get().unwrap();
 
         // check if we're able to format
         match capabilities.document_formatting_provider {
             Some(lsp::OneOf::Left(true)) | Some(lsp::OneOf::Right(_)) => (),
             // None | Some(false)
-            _ => return Ok(Vec::new()),
+            _ => return None,
         };
         // TODO: return err::unavailable so we can fall back to tree sitter formatting
 
@@ -605,9 +605,13 @@ impl Client {
             work_done_progress_params: lsp::WorkDoneProgressParams { work_done_token },
         };
 
-        let response = self.request::<lsp::request::Formatting>(params).await?;
+        let request = self.call::<lsp::request::Formatting>(params);
 
-        Ok(response.unwrap_or_default())
+        Some(async move {
+            let json = request.await?;
+            let response: Vec<lsp::TextEdit> = serde_json::from_value(json)?;
+            Ok(response)
+        })
     }
 
     pub async fn text_document_range_formatting(
diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs
index b2c02927..a27be8e6 100644
--- a/helix-view/src/document.rs
+++ b/helix-view/src/document.rs
@@ -386,21 +386,24 @@ impl Document {
     /// If supported, returns the changes that should be applied to this document in order
     /// to format it nicely.
     pub fn format(&self) -> Option<impl Future<Output = LspFormatting> + 'static> {
-        if let Some(language_server) = self.language_server.clone() {
+        if let Some(language_server) = self.language_server() {
             let text = self.text.clone();
-            let id = self.identifier();
+            let offset_encoding = language_server.offset_encoding();
+            let request = language_server.text_document_formatting(
+                self.identifier(),
+                lsp::FormattingOptions::default(),
+                None,
+            )?;
+
             let fut = async move {
-                let edits = language_server
-                    .text_document_formatting(id, lsp::FormattingOptions::default(), None)
-                    .await
-                    .unwrap_or_else(|e| {
-                        log::warn!("LSP formatting failed: {}", e);
-                        Default::default()
-                    });
+                let edits = request.await.unwrap_or_else(|e| {
+                    log::warn!("LSP formatting failed: {}", e);
+                    Default::default()
+                });
                 LspFormatting {
                     doc: text,
                     edits,
-                    offset_encoding: language_server.offset_encoding(),
+                    offset_encoding,
                 }
             };
             Some(fut)