tauri-apps/tauri · error
unable to serialize response error string to json
Error message
unable to serialize response error string to json
What it means
When an IPC command returns an error and the response must be delivered back to the webview via `window.eval`, Tauri formats the error string into the callback JS. `format_callback` uses serde to JSON-encode the message; if that fails this panic fires, which should be impossible for a plain string.
Solutions
- Return simple, well-formed string errors from commands (avoid exotic characters in error messages).
- Upgrade tauri; modern versions handle callback formatting without panicking.
- Prefer the channel-based response path (or `Result<T, E>` with `Serialize` errors) which bypasses this eval formatting.
- If reproducible, log the failing error string and file an issue — it indicates a serde bug or patched dependency.
Example fix
// before
Err(format!("failed: {:?}", raw_bytes)) // may contain invalid content
// after
Err(format!("failed: {}", String::from_utf8_lossy(&raw_bytes))) Defensive patterns
Strategy: try-catch
Try / catch
// In commands, return clean serializable errors
#[tauri::command]
fn run() -> Result<(), String> {
inner().map_err(|e| e.to_string()) // plain UTF-8 string, no exotic bytes
} Prevention
- Return simple string or typed Serialize errors from commands
- Strip binary/control data out of error messages
- Prefer channel-based responses for large payloads
When it happens
Trigger: An invoke handler returns `Err(e)` whose `Display` output is serialized via `format_callback::format`, and serde_json serialization of the string unexpectedly fails.
Common situations: Extremely rare in practice; seen when custom `RuntimeError`/error types contribute control characters or when running patched/old tauri versions where the callback formatting was fragile.
Understand the failure class
Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.
Related errors
- failed to serialize scope
- invalid IPC request URL
- missing command scope for key
- [TAURI] Couldn't find callback id
- Can't extract file name from path
AI-assisted analysis of tauri-apps/tauri@460ec35447 (2026-09-18).
Data as JSON: /api/errors/f4183e91ebe112f0.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tauri/src/ipc/protocol.rs:333
request,
Box::new(move |webview, cmd, response, callback, error| {
use crate::ipc::Channel;
#[cfg(feature = "tracing")]
let _respond_span = tracing::trace_span!(
parent: &request_span,
"ipc::request::respond"
)
.entered();
fn responder_eval<R: Runtime>(
webview: &crate::Webview<R>,
js: crate::Result<String>,
error: CallbackFn,
) {
let eval_js = js.unwrap_or_else(|e| {
crate::ipc::format_callback::format(error, &e.to_string())
.expect("unable to serialize response error string to json")
});
let _ = webview.eval(eval_js);
}
let can_use_channel_for_response = cmd != crate::ipc::channel::FETCH_CHANNEL_DATA_COMMAND
&& !options.custom_protocol_ipc_blocked;
#[cfg(feature = "tracing")]
let mime_type = match &response {
InvokeResponse::Ok(InvokeResponseBody::Json(_)) => mime::APPLICATION_JSON,
InvokeResponse::Ok(InvokeResponseBody::Raw(_)) => mime::APPLICATION_OCTET_STREAM,
InvokeResponse::Err(_) => mime::APPLICATION_JSON,
};
#[cfg(feature = "tracing")]
let _response_span = match &response {
InvokeResponse::Ok(InvokeResponseBody::Json(v)) => tracing::trace_span!(
"ipc::request::response",View on GitHub (pinned to 460ec35447)