{"id":2287,"date":"2022-03-01T08:25:36","date_gmt":"2022-03-01T14:25:36","guid":{"rendered":"https:\/\/www.becomebetterprogrammer.com\/?p=2287"},"modified":"2022-04-25T09:32:37","modified_gmt":"2022-04-25T14:32:37","slug":"rust-panic-vs-error","status":"publish","type":"post","link":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-panic-vs-error\/","title":{"rendered":"Rust: Panic vs Error &#8211; What is the difference?"},"content":{"rendered":"\n<p>In most programming languages, there is a way to programmatically throw errors or an application crashing due to an unexpected error. While this same concept applies in Rust, it is not enough to talk about an error, but also to panic. As weird as it sounds when there is <em>panic <\/em>in Rust it means an error has occurred. In this article, we will discuss the differences between panic and error in Rust.<\/p>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-panic-vs-error\/#Recoverable_and_Unrecoverable_Errors\" >Recoverable and Unrecoverable Errors<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-panic-vs-error\/#What_is_an_error_in_Rust\" >What is an error in Rust?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-panic-vs-error\/#What_is_a_Panic_in_Rust\" >What is a Panic in Rust?<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-panic-vs-error\/#What_can_trigger_a_panic\" >What can trigger a panic?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-panic-vs-error\/#How_to_trigger_a_panic\" >How to trigger a panic?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-panic-vs-error\/#Viewing_the_strack_trace_or_backtrace\" >Viewing the strack trace or backtrace<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-panic-vs-error\/#Conclusion\" >Conclusion<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Recoverable_and_Unrecoverable_Errors\"><\/span>Recoverable and Unrecoverable Errors<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>In Rust, there is a clear distinction between recoverable and unrecoverable errors, but before we move forward with these concepts, this might sound confusing at first if you have a background in any other programming language such as JavaScript or C# as an error is understood to simply be an error. For instance, let&#8217;s look at the following JavaScript snippet of code.<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>async function insertCar({\n   brand,   \n   model,\n   year,\n   isUsed\n}) {\n  try {\n    if (isUsed) {\n       throw new Error(\"Cannot insert used cars\");\n    }\n\n    const result = await db.car.add({ brand, model, year });\n    return { success: true, id: result.id };\n  } catch(error) {\n    return { success: false, id: undefined };\n  } \n}<\/code><\/pre>\n\n\n\n<p>Notice the <code>insertCar<\/code> function adds a new car record to the database as long as the car is not used. Otherwise, throw an error.<\/p>\n\n\n\n<p>One important aspect to notice is the logic of this function is wrapped within a <code>try<\/code>\/<code>catch<\/code>. A try\/catch is an error-handling mechanism to prevent the code from completely crashing when there is an error. <strong>While this is a common practice among many programming languages, there is no <code>try<\/code>\/<code>catch<\/code> in Rust.<\/strong><\/p>\n\n\n\n<p>If you pay close attention to our previous snippet of code, there are two possible sources of error. A custom error is triggered by a custom logic or an error triggered by the code.<\/p>\n\n\n\n<pre class=\"wp-block-code language-javascript\"><code>    if (isUsed) {\n       \/\/ generate custom error\n       throw new Error(\"Cannot insert used cars\");\n    }\n    \n    \/\/ an error could happen if there is not a connection\n    \/\/ established with the database\n    const result = await db.car.add({ brand, model, year });<\/code><\/pre>\n\n\n\n<p>One good question to ask is: <em>Does the custom error <code>throw new Error(\"Cannot insert used cars\");<\/code>, really need to crash the whole program in case there is not a <code>try<\/code>\/<code>catch<\/code>?<\/em> <\/p>\n\n\n\n<p>Chances are there is no need to crash the whole program. One good indicator of this is that we are returning an object with the properties <code>success<\/code> and <code>id<\/code> from executing the <code>insertCar<\/code> function. We could infer that whoever calls this function will check if the car was successfully added to the database or not by checking the returned value of the property <code>success<\/code>. <\/p>\n\n\n\n<p>In the world of Rust, we would define this kind of error as a recoverable error. As the name suggests, <strong>recoverable errors do not cause the program to terminate completely<\/strong>, and the code logic is properly set to handle these scenarios when encountering these kinds of errors.<\/p>\n\n\n\n<p>However, since the <code>try<\/code>\/<code>catch<\/code> is required in the snippet of code to prevent the program crashing, there wouldn&#8217;t be a way to determine if this is an error that our code logic correctly handles. What if we get an error from the database saying that the <code>year<\/code> must be a number in the case we pass a string value? Should we terminate the whole process? Should we continue running the rest of the code?<\/p>\n\n\n\n<p>With the <code>try<\/code>\/<code>catch<\/code>, we are under the assumption that all errors are unrecoverable. <strong>Unrecoverable errors cause a program to terminate immediately.<\/strong> Hence, it is common to use that error-handling mechanism if there is more logic that needs to be processed regardless of whether, i.e., it correctly inserted a new car record in the database or not. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"What_is_an_error_in_Rust\"><\/span>What is an error in Rust?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>To understand what an error is in Rust, it is recommended to look at the <a href=\"https:\/\/doc.rust-lang.org\/nightly\/std\/result\/enum.Result.html\" target=\"_blank\" rel=\"noreferrer noopener\"><code>Result<\/code> type<\/a> first, as you can see below:<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>pub enum Result&lt;T, E&gt; {\n    Ok(T),\n    Err(E),\n}<\/code><\/pre>\n\n\n\n<p>The <code>Result<\/code> type is typically used in Rust functions to return a success (<code>Ok<\/code>) value or an error (<code>Err<\/code>) value, which we can see with the following example.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>fn get_name(data: &amp;str) -&gt; Result&lt;&amp;str, &amp;str&gt; {\n    match !data.is_empty() {\n        true =&gt; Ok(data),\n        false =&gt; Err(\"Data is empty\"),\n    }\n}<\/code><\/pre>\n\n\n\n<p>The <code>get_name<\/code> function returns the <code>data<\/code> when the <code>data<\/code> parameter is not empty, or an error value if <code>data<\/code> is empty. Pretty straightforward.<\/p>\n\n\n\n<p>Let&#8217;s assume another function calls the <code>get_name<\/code> function which prints the returned value.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>fn main() {\n    let my_str = \"\";\n    let name = get_name(&amp;my_str);\n\n    if name.is_ok() {\n        print!(\"It is Ok {}\", name.ok().unwrap());\n    } else {\n        print!(\"It is an error value {}\", name.err().unwrap());\n    }\n}<\/code><\/pre>\n\n\n\n<p>Typically, in other programming languages, it is common to think of <em>throwing<\/em> errors. This means when there is an error in the code, all the subsequent processes will not be executed unless it is handled correctly via <code>try<\/code>\/<code>catch<\/code>. However, there is no such thing as a <code>try<\/code>\/<code>catch<\/code> in Rust. <\/p>\n\n\n\n<p><strong>Whenever there is a value type <code>Result&lt;T, E&gt;<\/code>, there is a recoverable error that allows to access the error value without the need to break the whole program.<\/strong> In the previous example, the program will print <em>&#8220;It is an error value Data is empty&#8221;<\/em> as <code>my_str<\/code> string literal is empty. In other programming languages, we wouldn&#8217;t have reached past defining the value for the variable <code>name<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"What_is_a_Panic_in_Rust\"><\/span>What is a Panic in Rust?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p><strong>A panic in Rust more specifically <code><a href=\"https:\/\/doc.rust-lang.org\/std\/macro.panic.html\" target=\"_blank\" rel=\"noopener\">panic!()<\/a><\/code> is a macro that terminates the program when it comes across with an unrecoverable error.<\/strong> In other words, talking about panic is referring to a critical error.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"What_can_trigger_a_panic\"><\/span>What can trigger a panic?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Panics could be originated by using methods such as <code>unwrap<\/code> when attempting to extract the value of an <code><a href=\"https:\/\/doc.rust-lang.org\/std\/option\/enum.Option.html\" target=\"_blank\" rel=\"noopener\">Option<\/a><\/code> that is <code>None<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>fn main() {\n    let option_with_value: Option&lt;&amp;str&gt; = Some(\"What up\");\n    let option_without_value: Option&lt;&amp;str&gt; = None;\n\n    option_with_value.unwrap(); \/\/ it returns the string literal \"'\n    option_without_value.unwrap(); \/\/ it panics as there's is no value\n}\n\nfn get_name(data: &amp;str) -&gt; Result&lt;&amp;str, &amp;str&gt; {\n    match !data.is_empty() {\n        true =&gt; Ok(data),\n        false =&gt; Err(\"Data is empty\"),\n    }\n}<\/code><\/pre>\n\n\n\n<p>Remember this example used to explain the <code>Result&lt;T, E&gt;<\/code>? You can check it out below:<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>fn main() {\n    let my_str = \"\";\n    let name = get_name(&amp;my_str);\n\n    if name.is_ok() {\n        print!(\"It is Ok {}\", name.ok().unwrap());\n    } else {\n        print!(\"It is an error value {}\", name.err().unwrap());\n    }\n}<\/code><\/pre>\n\n\n\n<p>We were doing a conditional check on purpose to define whether to call the <code>unwrap<\/code> method after triggering either the <code>ok()<\/code> or the <code>err()<\/code> method. These methods are helper methods that return the <code>Some<\/code> value of its related result. For instance, if the <code>Result<\/code> is <code>Ok(data<\/code>), the <code>ok()<\/code> method will return <code>Some(data)<\/code> unless it recognizes an <code>Err<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>   #&#91;inline]\n   #&#91;stable(feature = \"rust1\", since = \"1.0.0\")]\n    pub fn ok(self) -&gt; Option&lt;T&gt; {\n        match self {\n            Ok(x) =&gt; Some(x),\n            Err(_) =&gt; None,\n        }\n    }<\/code><\/pre>\n\n\n\n<p>If it recognizes an <code>Err<\/code>, the <code>ok()<\/code> method returns <code>None<\/code>. If we try to use the <code>unwrap<\/code> method on a <code>None<\/code> value, it will panic.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>\/\/ this would panic if value is None\nprint!(\"It is Ok {}\", name.ok().unwrap()); <\/code><\/pre>\n\n\n\n<p>On the other hand, the <code>err()<\/code> method returns <code>Some(error_message)<\/code> when it recognizes the <code>Result<\/code> to be an error, or <code>None<\/code> if the result was a success (<code>Ok<\/code>).<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>    #&#91;inline]\n    #&#91;stable(feature = \"rust1\", since = \"1.0.0\")]\n    pub fn err(self) -&gt; Option&lt;E&gt; {\n        match self {\n            Ok(_) =&gt; None,\n            Err(x) =&gt; Some(x),\n        }\n    }<\/code><\/pre>\n\n\n\n<p>In a similar case, if the <code>err()<\/code> method returns <code>None<\/code> and we attempt to use the <code>unwrap<\/code> method on a <code>None<\/code> value, it will panic.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>\/\/ this would panic if value is None\nprint!(\"It is an error value {}\", name.err().unwrap());<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"How_to_trigger_a_panic\"><\/span>How to trigger a panic?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>It is possible to manually panic the Rust program. <strong>To use the panic macro, invoke it as if you were triggering a function.<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>fn main() {\n    let name = \"Andres\";\n\n    panic!();\n\n    print!(\"Hello! {}\", name); \/\/ code will never reach here\n}<\/code><\/pre>\n\n\n\n<p>This code will fail as soon as it triggers the <code>panic!()<\/code> macro with the following message:<\/p>\n\n\n\n<p><code>thread 'main' panicked at 'explicit panic'<\/code><\/p>\n\n\n\n<p>Unfortunately, this doesn&#8217;t provide much information as to why the program panicked besides knowing it panicked in the &#8220;main&#8221; thread (or <code>main<\/code> function). For better visibility, it is possible to add a custom message to the panic.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>fn main() {\n    let name = \"Andres\";\n\n    panic!(\"Example of failing to run print! macro\");\n\n    print!(\"Hello! {}\", name); \/\/ code will never reach here\n}<\/code><\/pre>\n\n\n\n<p>Now, whenever this panic triggers, the terminal will display the custom message. <\/p>\n\n\n\n<p><code>thread 'main' panicked at 'Example of failing to run print! macro'<\/code><\/p>\n\n\n\n<p>This is useful when having multiple panic statements in an application.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Viewing_the_strack_trace_or_backtrace\"><\/span>Viewing the strack trace or backtrace<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p>Similar to other programming languages, panics provide a stack trace or backtrace of an error. However, <strong>the backtrace is not displayed in the terminal unless the environment variable <code>RUST_BACKTRACE<\/code> is set to a value different than 0<\/strong>.<\/p>\n\n\n\n<p>Hence, if you execute the following command statement in the previous code example,<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>RUST_BACKTRACE=1 cargo run<\/code><\/pre>\n\n\n\n<p>You should get a stack trace similar to the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>thread 'main' panicked at 'Example of failing to run print! macro', src\\main.rs:4:5\nstack backtrace:\n   0: rust_begin_unwind\n             at \/rustc\/db9d1b20bba1968c1ec1fc49616d4742c1725b4b\\\/library\\std\\src\/panicking.rs:498:5\n   1: core::panicking::panic_fmt\n             at \/rustc\/db9d1b20bba1968c1ec1fc49616d4742c1725b4b\\\/library\\core\\src\/panicking.rs:107:14\n   2: rust_playground::main\n             at .\\src\\main.rs:4:5\n   3: core::ops::function::FnOnce::call_once\n             at \/rustc\/db9d1b20bba1968c1ec1fc49616d4742c1725b4b\\library\\core\\src\\ops\/function.rs:227:5<\/code><\/pre>\n\n\n\n<p>Remember, the value of the environment variable can be anything besides 0. All of the following statements will display the backtrace.<\/p>\n\n\n\n<pre class=\"wp-block-code language-bash\"><code>RUST_BACKTRACE=6 cargo run\nRUST_BACKTRACE='get trace' cargo run\nRUST_BACKTRACE=true cargo run\nRUST_BACKTRACE=false cargo run<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>All in all, Rust has two kinds of errors: An error value returned from the <code>Result<\/code> type, and an error generated from triggering the <code>panic!<\/code> macro. The <code>Result<\/code> type returns a recoverable error, or in other words, an error that doesn&#8217;t cause the program to terminate. On the other hand, the <code>panic!<\/code> macro triggers an error that is unrecoverable or that causes the Rust program to terminate immediately. <\/p>\n\n\n\n<p><strong>Was this article helpful?<\/strong><\/p>\n\n\n\n<p><strong>I hope this article helped you to clarify doubts and concepts of Rust, especially to those new to this fascinating programming language<\/strong>.<\/p>\n\n\n\n<p>Share your thoughts by replying on Twitter of <a href=\"https:\/\/twitter.com\/bbprogrammer\" target=\"_blank\" rel=\"noreferrer noopener\">Become A Better Programmer<\/a> or to <a href=\"https:\/\/twitter.com\/arealesramirez\" target=\"_blank\" rel=\"noreferrer noopener\">personal my Twitter account<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-embed aligncenter is-type-rich is-provider-twitter wp-block-embed-twitter\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"twitter-tweet\" data-width=\"550\" data-dnt=\"true\"><p lang=\"en\" dir=\"ltr\">Don&#39;t panic! it is just a new <a href=\"https:\/\/twitter.com\/hashtag\/Rust?src=hash&amp;ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"noopener\">#Rust<\/a> article!<br><br>In our latest blog post, we explain the differences between panic and an error in <a href=\"https:\/\/twitter.com\/hashtag\/rustlang?src=hash&amp;ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"noopener\">#rustlang<\/a>.<br><br>Did you know both, a panic and an error, are errors? <br><br>Weird, isn&#39;t it? <a href=\"https:\/\/t.co\/HQNso9IN70\">https:\/\/t.co\/HQNso9IN70<\/a><\/p>&mdash; Become A Better Programmer (@bbprogrammer) <a href=\"https:\/\/twitter.com\/bbprogrammer\/status\/1498667433472708612?ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"noopener\">March 1, 2022<\/a><\/blockquote><script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script>\n<\/div><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>In this article, you will learn the difference between a panic and an error in Rust regardless of both representing an error in this programming language.<\/p>\n","protected":false},"author":1,"featured_media":2294,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[31],"tags":[],"class_list":["post-2287","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-rust","generate-columns","tablet-grid-50","mobile-grid-100","grid-parent","grid-50"],"_links":{"self":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts\/2287","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/comments?post=2287"}],"version-history":[{"count":5,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts\/2287\/revisions"}],"predecessor-version":[{"id":2451,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts\/2287\/revisions\/2451"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/media\/2294"}],"wp:attachment":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/media?parent=2287"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/categories?post=2287"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/tags?post=2287"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}