A conversation whose metadata fails to load disappears from every listing
- Status: Todo
- Kind: Bug
- Authors: jp
- Date: 2026-08-20
- Label: domain=conversation
- Label: package=jp_conversation
- Label: type=bug
Workspace::conversations() calls ensure_all_metadata_loaded, which logs a warn! for each conversation whose metadata will not load and leaves that conversation's cell unset. The iterator then filter_maps on cell.get(), so the conversation is dropped from the result and the call still succeeds.
// crates/jp_workspace/src/lib.rs
Err(error) => warn!(%id, %error, "Failed to load conversation metadata."),Every consumer therefore receives a listing that looks complete and is not: jp conversation ls, jp serve web, and jp_workspace_conversations in the FFI. Nothing in the returned value says a conversation was skipped.
A plausible input is a metadata.json written partially during a crash, or one mis-edited by hand — jp conversation edit --events actively encourages hand editing, so this is not a hypothetical shape.
The failure is worst in the macOS app. jp_ffi installs no tracing subscriber, so the warn! has nowhere to go: a conversation vanishes from the sidebar with no log line, no error, and no indication that the list is short. In the CLI at least the warning reaches stderr under the usual configuration.
The fix belongs at the jp_workspace layer rather than in any one consumer, so that all three agree about what a workspace contains. Something along the lines of a listing that carries the per-entry failures alongside the conversations that did load, letting each consumer decide how to present them — the sidebar could show a row that says the conversation could not be read, and jp conversation ls could print a count of what it skipped.
Found while triaging review feedback on the macOS app PR (dcdpr/jp#1008, comment 3815419227). Not introduced there; the app only made an existing silent failure completely silent.