persistence: More error contexts (#40787)

Lukas Wirth and David Kleingeld created

Release Notes:

- N/A *or* Added/Fixed/Improved ...

Co-authored-by: David Kleingeld <davidsk@zed.dev>

Change summary

crates/editor/src/items.rs                | 17 +++++++++++++----
crates/project/src/buffer_store.rs        |  7 +++++--
crates/workspace/src/persistence/model.rs |  3 ++-
crates/worktree/src/worktree.rs           |  6 +++---
4 files changed, 23 insertions(+), 10 deletions(-)

Detailed changes

crates/editor/src/items.rs 🔗

@@ -1079,12 +1079,17 @@ impl SerializableItem for Editor {
                 }
             }
             Ok(None) => {
-                return Task::ready(Err(anyhow!("No path or contents found for buffer")));
+                return Task::ready(Err(anyhow!(
+                    "Unable to deserialize editor: No entry in database for item_id: {item_id} and workspace_id {workspace_id:?}"
+                )));
             }
             Err(error) => {
                 return Task::ready(Err(error));
             }
         };
+        log::debug!(
+            "Deserialized editor {item_id:?} in workspace {workspace_id:?}, {serialized_editor:?}"
+        );
 
         match serialized_editor {
             SerializedEditor {
@@ -1112,7 +1117,8 @@ impl SerializableItem for Editor {
                     // First create the empty buffer
                     let buffer = project
                         .update(cx, |project, cx| project.create_buffer(true, cx))?
-                        .await?;
+                        .await
+                        .context("Failed to create buffer while deserializing editor")?;
 
                     // Then set the text so that the dirty bit is set correctly
                     buffer.update(cx, |buffer, cx| {
@@ -1154,7 +1160,9 @@ impl SerializableItem for Editor {
                 match opened_buffer {
                     Some(opened_buffer) => {
                         window.spawn(cx, async move |cx| {
-                            let (_, buffer) = opened_buffer.await?;
+                            let (_, buffer) = opened_buffer
+                                .await
+                                .context("Failed to open path in project")?;
 
                             // This is a bit wasteful: we're loading the whole buffer from
                             // disk and then overwrite the content.
@@ -1220,7 +1228,8 @@ impl SerializableItem for Editor {
             } => window.spawn(cx, async move |cx| {
                 let buffer = project
                     .update(cx, |project, cx| project.create_buffer(true, cx))?
-                    .await?;
+                    .await
+                    .context("Failed to create buffer")?;
 
                 cx.update(|window, cx| {
                     cx.new(|cx| {

crates/project/src/buffer_store.rs 🔗

@@ -24,7 +24,7 @@ use rpc::{
 
 use std::{io, sync::Arc, time::Instant};
 use text::{BufferId, ReplicaId};
-use util::{ResultExt as _, TryFutureExt, debug_panic, maybe, rel_path::RelPath};
+use util::{ResultExt as _, TryFutureExt, debug_panic, maybe, paths::PathStyle, rel_path::RelPath};
 use worktree::{File, PathChange, ProjectEntryId, Worktree, WorktreeId};
 
 /// A set of open buffers.
@@ -621,8 +621,11 @@ impl LocalBufferStore {
             let load_file = worktree.load_file(path.as_ref(), cx);
             let reservation = cx.reserve_entity();
             let buffer_id = BufferId::from(reservation.entity_id().as_non_zero_u64());
+            let path = path.clone();
             cx.spawn(async move |_, cx| {
-                let loaded = load_file.await?;
+                let loaded = load_file.await.with_context(|| {
+                    format!("Could not open path: {}", path.display(PathStyle::local()))
+                })?;
                 let text_buffer = cx
                     .background_spawn(async move {
                         text::Buffer::new(ReplicaId::LOCAL, buffer_id, loaded.text)

crates/workspace/src/persistence/model.rs 🔗

@@ -3,7 +3,7 @@ use crate::{
     Member, Pane, PaneAxis, SerializableItemRegistry, Workspace, WorkspaceId, item::ItemHandle,
     path_list::PathList,
 };
-use anyhow::Result;
+use anyhow::{Context, Result};
 use async_recursion::async_recursion;
 use collections::IndexSet;
 use db::sqlez::{
@@ -220,6 +220,7 @@ impl SerializedPaneGroup {
                 let new_items = serialized_pane
                     .deserialize_to(project, &pane, workspace_id, workspace.clone(), cx)
                     .await
+                    .context("Could not deserialize pane)")
                     .log_err()?;
 
                 if pane

crates/worktree/src/worktree.rs 🔗

@@ -1706,9 +1706,9 @@ impl LocalWorktree {
             refresh.recv().await;
             log::trace!("refreshed entry {path:?} in {:?}", t0.elapsed());
             let new_entry = this.read_with(cx, |this, _| {
-                this.entry_for_path(&path)
-                    .cloned()
-                    .context("reading path after update")
+                this.entry_for_path(&path).cloned().with_context(|| {
+                    format!("Could not find entry in worktree for {path:?} after refresh")
+                })
             })??;
             Ok(Some(new_entry))
         })