From 788bc8d021ab0ec2d58837b129c178300b2c2a39 Mon Sep 17 00:00:00 2001 From: Kyle Kelley Date: Mon, 18 Sep 2023 15:07:33 -0700 Subject: fix(cli): Enhanced errors for Jupyter (#20530) --- cli/tools/jupyter/server.rs | 83 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 71 insertions(+), 12 deletions(-) (limited to 'cli/tools/jupyter') diff --git a/cli/tools/jupyter/server.rs b/cli/tools/jupyter/server.rs index f0e523e1e..f53f5209c 100644 --- a/cli/tools/jupyter/server.rs +++ b/cli/tools/jupyter/server.rs @@ -408,25 +408,84 @@ impl JupyterServer { tokio::time::sleep(std::time::Duration::from_millis(5)).await; } else { let exception_details = exception_details.unwrap(); - let name = if let Some(exception) = exception_details.exception { - if let Some(description) = exception.description { - description - } else if let Some(value) = exception.value { - value.to_string() + + // Determine the exception value and name + let (name, message, stack) = + if let Some(exception) = exception_details.exception { + let result = self + .repl_session + .call_function_on_args( + r#" + function(object) { + if (object instanceof Error) { + const name = "name" in object ? String(object.name) : ""; + const message = "message" in object ? String(object.message) : ""; + const stack = "stack" in object ? String(object.stack) : ""; + return JSON.stringify({ name, message, stack }); + } else { + const message = String(object); + return JSON.stringify({ name: "", message, stack: "" }); + } + } + "# + .into(), + &[exception], + ) + .await?; + + match result.result.value { + Some(serde_json::Value::String(str)) => { + if let Ok(object) = + serde_json::from_str::>(&str) + { + let get = |k| object.get(k).cloned().unwrap_or_default(); + (get("name"), get("message"), get("stack")) + } else { + eprintln!("Unexpected result while parsing JSON {str}"); + ("".into(), "".into(), "".into()) + } + } + _ => { + eprintln!("Unexpected result while parsing exception {result:?}"); + ("".into(), "".into(), "".into()) + } + } } else { - "undefined".to_string() - } + eprintln!("Unexpectedly missing exception {exception_details:?}"); + ("".into(), "".into(), "".into()) + }; + + let stack = if stack.is_empty() { + format!( + "{}\n at ", + serde_json::to_string(&message).unwrap() + ) + } else { + stack + }; + let traceback = format!("Stack trace:\n{stack}") + .split('\n') + .map(|s| s.to_owned()) + .collect::>(); + + let ename = if name.is_empty() { + "Unknown error".into() + } else { + name + }; + + let evalue = if message.is_empty() { + "(none)".into() } else { - "Unknown exception".to_string() + message }; - // TODO(bartlomieju): fill all the fields msg .new_message("error") .with_content(json!({ - "ename": name, - "evalue": " ", // Fake value, otherwise old Jupyter frontends don't show the error - "traceback": [], + "ename": ename, + "evalue": evalue, + "traceback": traceback, })) .send(&mut *self.iopub_socket.lock().await) .await?; -- cgit v1.2.3