BloopAI/vibe-kanban · error
Workspace serialization should not fail
Error message
Workspace serialization should not fail
What it means
This panic comes from `.expect()` on `serde_json::to_value(workspace)` in `workspace_patch::add` (crates/services/src/services/events/patches.rs:72). The library assumes `WorkspaceWithStatus` always serializes to JSON; serde returns `Err` only when a custom `Serialize` implementation errors (e.g. serializing a map with non-string keys or a manual impl returning Err). This is treated as an internal invariant, not an expected runtime failure.
Source
Thrown at crates/services/src/services/events/patches.rs:72
/// Helper functions for creating workspace-specific patches
pub mod workspace_patch {
use super::*;
fn workspace_path(workspace_id: Uuid) -> String {
format!(
"/workspaces/{}",
escape_pointer_segment(&workspace_id.to_string())
)
}
pub fn add(workspace: &WorkspaceWithStatus) -> Patch {
Patch(vec![PatchOperation::Add(AddOperation {
path: workspace_path(workspace.id)
.try_into()
.expect("Workspace path should be valid"),
value: serde_json::to_value(workspace)
.expect("Workspace serialization should not fail"),
})])
}
pub fn replace(workspace: &WorkspaceWithStatus) -> Patch {
Patch(vec![PatchOperation::Replace(ReplaceOperation {
path: workspace_path(workspace.id)
.try_into()
.expect("Workspace path should be valid"),
value: serde_json::to_value(workspace)
.expect("Workspace serialization should not fail"),
})])
}
pub fn remove(workspace_id: Uuid) -> Patch {
Patch(vec![PatchOperation::Remove(RemoveOperation {
path: workspace_path(workspace_id)
.try_into()
.expect("Workspace path should be valid"),View on GitHub (pinned to 4deb7eca8f)
Solutions
- Inspect `WorkspaceWithStatus` (and nested types) for custom `Serialize` impls that can return Err; fix the impl so it cannot fail.
- If a field serializes a map with non-string keys, convert keys to strings first (e.g. BTreeMap<String, T>) before serializing.
- If fallibility is real, replace `.expect(...)` with error propagation (return Result<Patch, serde_json::Error>) and handle at the event-emission layer.
- Regenerate/verify derived types with `pnpm run generate-types` after changing the struct.
Example fix
// before
value: serde_json::to_value(workspace)
.expect("Workspace serialization should not fail"),
// after
value: serde_json::to_value(workspace).unwrap_or_else(|e| {
panic!("failed to serialize workspace {}: {e}", workspace.id)
}),
// or propagate: return Result<Patch, serde_json::Error> Defensive patterns
Strategy: validation
Validate before calling
let value = serde_json::to_value(&workspace)
.map_err(|e| anyhow::anyhow!("workspace serialization failed: {e}"))?;
// proceed with Patch construction using `value` Type guard
fn serializable<T: serde::Serialize>(v: &T) -> Option<serde_json::Value> {
serde_json::to_value(v).ok()
} Try / catch
match serde_json::to_value(workspace) {
Ok(v) => /* build patch with v */,
Err(e) => log::error!("workspace {} serialization failed: {e}", workspace.id),
} Prevention
- Prefer derived #[derive(Serialize)] over hand-written fallible impls.
- Avoid serializing maps with non-string keys; pre-convert keys to String.
- Keep Rust and TS types in sync via pnpm run generate-types.
- Add a round-trip test: to_value then from_value for WorkspaceWithStatus.
When it happens
Trigger: Calling `workspace_patch::add(&WorkspaceWithStatus)` when `serde_json::to_value` fails — only possible if a type inside `WorkspaceWithStatus` has a custom/fallible `Serialize` impl (e.g. serializing a HashMap with non-string keys, or a manual impl returning Err).
Common situations: Developers encounter this after adding a field with a hand-written `Serialize` implementation that can fail, or after swapping a struct field to a map keyed by UUIDs/other non-string types.
Related errors
- Scratch serialization should not fail
- Default profiles v3 JSON is invalid
- Execution process serialization should not fail
- Scratch path should be valid
- request_id called for unsupported request variant
AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29).
Data as JSON: /api/errors/803c87272f8ee311.
Report an issue: GitHub.