rust-lang/rust-analyzer · warning
serialized runnable
Error message
serialized runnable
What it means
A unit test asserts that the Runnable struct serializes to JSON without failing. serde_json::to_value returns Err only if a map key is not a string or serialization is otherwise impossible; the expect turns that into a panic labeled "serialized runnable". Failure indicates the Runnable/RunnableArgs serde derive or a manual Serialize impl is broken.
Source
Thrown at crates/rust-analyzer/src/lsp/ext.rs:1005
"--lib".into(),
],
executable_args: vec!["my_test".into(), "--exact".into()],
}),
};
let expected = json!({
"label": "cargo test -p my-crate",
"kind": "cargo",
"args": {
"environment": {"RUSTC_TOOLCHAIN": "/toolchain"},
"cwd": "/project",
"overrideCargo": null,
"workspaceRoot": "/project",
"cargoArgs": ["test", "--package", "my-crate", "--lib"],
"executableArgs": ["my_test", "--exact"],
}
});
let serialized = serde_json::to_value(&runnable).expect("serialized runnable");
assert_eq!(serialized, expected);
let deserialized: Runnable =
serde_json::from_value(expected).expect("cargo runnable should deserialize");
let RunnableArgs::Cargo(cargo) = &deserialized.args else {
panic!("expected Cargo variant, got {:?}", deserialized.args);
};
assert_eq!(cargo.cargo_args, vec!["test", "--package", "my-crate", "--lib"]);
assert_eq!(cargo.executable_args, vec!["my_test", "--exact"]);
}
#[test]
fn shell_runnable_round_trips() {
let runnable = Runnable {
label: "nextest test_one".to_owned(),
location: None,
args: RunnableArgs::Shell(ShellRunnableArgs {
environment: [("RUSTC_TOOLCHAIN".to_owned(), "/toolchain".to_owned())]View on GitHub (pinned to e8f7e90aa3)
Solutions
- Run the failing test with RUST_BACKTRACE=1 to locate which field's Serialize impl errors.
- Fix the Serialize implementation/serde attributes on Runnable or its args so to_value cannot fail (all map keys must be strings).
- Regenerate/adjust the expected JSON in the test only after confirming the new wire format is intended.
- If the extension protocol intentionally changed, update the client extension's expected payload shape too.
Defensive patterns
Strategy: validation
Validate before calling
// in the test, surface the underlying serde error instead of an opaque panic
let serialized = serde_json::to_value(&runnable)
.unwrap_or_else(|e| panic!("runnable failed to serialize: {e}")); Type guard
fn serializable<T: serde::Serialize>(v: &T) -> bool {
serde_json::to_value(v).is_ok()
} Prevention
- Keep all map keys in serde payloads as String.
- Prefer derived Serialize over manual impls for LSP extension types.
- Run cargo test -p rust-analyzer after touching lsp_ext types.
- Avoid serde attributes (like untagged) that complicate serialization guarantees.
When it happens
Trigger: Modifying the Runnable, RunnableArgs (Cargo/Shell), or related lsp_ext types so serde_json::to_value fails — e.g. a non-string map key or a Serialize impl returning an error — then running cargo test -p rust-analyzer in crates/rust-analyzer/src/lsp/ext.rs.
Common situations: Contributors changing the rust-analyzer LSP extension API (runnable payload schema), switching serde attributes (untagged/adjacent tagging), or adding types that cannot serialize to JSON.
Related errors
AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03).
Data as JSON: /api/errors/460221534d68b78e.
Report an issue: GitHub.