{"id":12935,"date":"2017-01-10T06:00:15","date_gmt":"2017-01-10T14:00:15","guid":{"rendered":"https:\/\/www.sapien.com\/blog\/?p=12935"},"modified":"2017-01-10T11:38:19","modified_gmt":"2017-01-10T19:38:19","slug":"friday-puzzle-what-does-a-catch-block-catch","status":"publish","type":"post","link":"https:\/\/dev.sapien.com\/blog\/2017\/01\/10\/friday-puzzle-what-does-a-catch-block-catch\/","title":{"rendered":"Friday Puzzle:  What does a Catch block catch?"},"content":{"rendered":"<p>On Friday, January 6, 2017, I posted the following puzzle on <a href=\"https:\/\/twitter.com\/juneb_get_help\/status\/817413653540417538\" target=\"_blank\">Twitter <\/a>and <a href=\"https:\/\/www.facebook.com\/SAPIENTech\/photos\/a.10151095012027283.433079.82797372282\/10154206375342283\/?type=3\" target=\"_blank\">Facebook<\/a> (<a href=\"https:\/\/www.facebook.com\/groups\/powershell\/permalink\/1309709699087205\/\" target=\"_blank\">here, too!<\/a>).<\/p>\n<p>It shows a <strong>Try<\/strong> block that encloses an expression with an intentional error and a <strong>Catch<\/strong> block that writes an error. But, when you run it, the error doesn&#8217;t appear as designed.<\/p>\n<p>The error is supposed to say &#8216;Cannot multiply by apple.&#8217; But, it doesn&#8217;t. What went wrong here?<\/p>\n<p style=\"padding-left: 30px;\"><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/Catch_DollarUnderscore.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-12936\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/Catch_DollarUnderscore.jpg\" alt=\"\" width=\"450\" height=\"335\" srcset=\"https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/Catch_DollarUnderscore.jpg 450w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/Catch_DollarUnderscore-300x223.jpg 300w\" sizes=\"auto, (max-width: 450px) 100vw, 450px\" \/><\/a><\/p>\n<p>I marked this week&#8217;s puzzle &#8220;beginner&#8221; not because it&#8217;s easy or obvious, but because almost everyone who&#8217;s written error handling for a PowerShell script has already run into this and is familiar with it.<\/p>\n<h1>The Solution: Catch catches the error<\/h1>\n<p>The answer is that the Catch block catches terminating errors. In a Catch block, $_ represents the error or <em>exception<\/em> that it caught. It does not contain any of the objects in the (now terminated) pipeline.<\/p>\n<p>Let&#8217;s run the code and see what happens.<\/p>\n<p style=\"padding-left: 30px;\"><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/Image1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-12942\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/Image1.png\" alt=\"\" width=\"783\" height=\"352\" srcset=\"https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/Image1.png 1106w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/Image1-300x135.png 300w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/Image1-768x345.png 768w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/Image1-1024x460.png 1024w\" sizes=\"auto, (max-width: 783px) 100vw, 783px\" \/><\/a><\/p>\n<p>An error occurs when PowerShell tries to multiply a string (&#8216;car&#8217;) by another string (&#8216;apple&#8217;). It&#8217;s a terminating error, that is, a serious error that stops the pipeline, so it falls into the Catch block, as designed. So far, so good.<\/p>\n<p>But, the error that the Catch block generates does not say &#8216;Cannot multiply by apple&#8217;. Instead, it says (color added for emphasis):<\/p>\n<pre class=\"output\"><span style=\"color: yellow;\">Cannot multiply by <\/span><span style=\"color: orange;\">Cannot convert value \"apple\" to type \"System.Int32\". Error: \"Input string was not in a correct format.\".<\/span><\/pre>\n<p>The <strong>Cannot multiply by<\/strong> comes from the\u00a0<a href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkId=821875\">Write-Error<\/a> message string. The next part of the message string is <strong>$_<\/strong>, the current object in the pipeline. But, the value of <strong>$_<\/strong> is not &#8216;apple&#8217;. Instead, its value is:<\/p>\n<pre class=\"output\"><span style=\"color: orange;\">Cannot convert value \"apple\" to type \"System.Int32\". Error: \"Input string was not in a correct format.\".<\/span><\/pre>\n<p>And, the type of the current object is not a string, like &#8216;apple&#8217;. It&#8217;s an <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.management.automation.errorrecord(v=vs.85).aspx\">ErrorRecord<\/a>. To figure this out, I comment-out the Write-Error command and replace it with strings that write the value of the current object and its type.<\/p>\n<p>These diagnostic strings &#8212; the ones that write out values and types &#8212; are one of my favorite tools. I use them whenever I get unexpected output.<\/p>\n<p style=\"padding-left: 30px;\"><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/Image2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-12943\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/Image2.png\" alt=\"\" width=\"804\" height=\"364\" srcset=\"https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/Image2.png 1347w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/Image2-300x136.png 300w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/Image2-768x348.png 768w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/Image2-1024x464.png 1024w\" sizes=\"auto, (max-width: 804px) 100vw, 804px\" \/><\/a><\/p>\n<p>What happened here is now a bit clearer.<\/p>\n<p>We started with an array of objects:<\/p>\n<pre class=\"output\">1, 2, 'apple', 3<\/pre>\n<p>And piped them to the ForEach-Object cmdlet.<\/p>\n<pre class=\"output\">1, 2, 'apple', 3 | ForEach-Object { &lt;expression&gt; }<\/pre>\n<p>ForEach-Object gets the items in the array one at a time and includes them in the expression. So, in the ForEach-Object expression, the value of $_ is the current array item.<\/p>\n<pre class=\"output\">PS C:\\&gt; 1, 2, 'apple', 3 | ForEach-Object { \"The current object: $_\" }\r\nThe current object: 1\r\nThe current object: 2\r\nThe current object: apple\r\nThe current object: 3<\/pre>\n<p>The expression multiples a string (&#8216;car&#8217;) by the current object. When the current object is an integer, the multiplication works.<\/p>\n<pre class=\"output\">PS C:\\&gt; 'car' * 3\r\ncarcarcar<\/pre>\n<p>NOTE: In PowerShell, multiplication is not commutative: (&#8216;car&#8217; * 3) -ne (3 * &#8216;car&#8217;). For more information, see <a href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkID=113208\">about_arithmetic_operators<\/a>.<\/p>\n<p>But, PowerShell won&#8217;t let you multiply a string by another string.<\/p>\n<pre class=\"output\">PS C:\\&gt; 'car' * 'apple'\r\n<span style=\"color: red;\">Cannot convert value \"apple\" to type \"System.Int32\". Error: \"Input string was not in a correct format.\"\r\nAt line:1 char:1\r\n+ 'car' * 'apple'\r\n+ ~~~~~~~~~~~~~~~\r\n+ CategoryInfo\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 : InvalidArgument: (:) [], RuntimeException\r\n+ FullyQualifiedErrorId : InvalidCastFromStringToInteger<\/span><\/pre>\n<p>When you try to multiply two strings, PowerShell declares a <em>terminating error, <\/em>an error so serious that it <em>terminates<\/em> or stops the pipeline. If the terminating error occurs in a <strong>Try<\/strong> block, as in this case, control falls to the <strong>Catch<\/strong> block. The <strong>$_<\/strong> still works, but the current object ($_) in the Catch block is not an item in the array of the now-terminated pipeline. It is the terminating error or exception that stopped the pipeline in the Try block.<\/p>\n<p>In this case, the terminating error, the value of $_, is:<\/p>\n<pre class=\"output\">Cannot convert value \"apple\" to type \"System.Int32\". Error: \"Input string was not in a correct format.\".<\/pre>\n<h1>The Fix<\/h1>\n<p>Once you&#8217;ve figured out what went wrong, it&#8217;s easy to come up with several different solutions. The simplest solution is to add an expression to the <a href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkId=821481\" target=\"_blank\">ForEach-Object<\/a> script block that assigns the current object to a variable (in this case, $x). Each time an object in the pipeline goes through the ForEach-Object script block, its value is assigned to $x, replacing the previous value. Then, if a terminating error occurs, you can use the $x variable in the error message.<\/p>\n<p style=\"padding-left: 30px;\"><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/image3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-12944\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/image3.png\" alt=\"\" width=\"841\" height=\"484\" srcset=\"https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/image3.png 1062w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/image3-300x173.png 300w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/image3-768x442.png 768w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/image3-1024x589.png 1024w\" sizes=\"auto, (max-width: 841px) 100vw, 841px\" \/><\/a><\/p>\n<p>When I first tried this solution many years ago, I was worried that the Try and Catch script blocks might have different scopes, requiring us to define the variable outside of the Try-Catch, but fortunately, they&#8217;re in the same scope. And terminating the pipeline doesn&#8217;t delete variables created in the pipeline.<\/p>\n<p>Someone suggested using the <a href=\"https:\/\/rkeithhill.wordpress.com\/2013\/07\/20\/powershell-v4-pipelinevariable-common-parameter\/\">PipelineVariable<\/a> common parameter to create the variable that saves the current object, but the pipeline variable is valid only as long as the pipeline is active.<\/p>\n<p>You might notice that, in the fix, I replaced the <a href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkId=821875\">Write-Error<\/a> cmdlet with the <a href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkID=145153\">Throw<\/a> statement. Write-Error works, too, but I usually omit it from Catch blocks because some folks think that it converts a terminating error to a non-terminating error, allowing the pipeline to continue. It doesn&#8217;t and I don&#8217;t want to confuse people, so, in my code, I use Throw.<\/p>\n<p style=\"padding-left: 30px;\"><a href=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/image4.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-12945\" src=\"https:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/image4.png\" alt=\"\" width=\"620\" height=\"460\" srcset=\"https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/image4.png 780w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/image4-300x223.png 300w, https:\/\/dev.sapien.com\/blog\/wp-content\/uploads\/2017\/01\/image4-768x570.png 768w\" sizes=\"auto, (max-width: 620px) 100vw, 620px\" \/><\/a><\/p>\n<h1>Summary<\/h1>\n<p>The moral of the story is to test everything in your scripts, including the errors. If the errors don&#8217;t print as you expected, throw some debugging code in there.<\/p>\n<p>Thanks to everyone on Facebook and Twitter who tried the puzzle. Thanks to those who submitted guesses (they were terrific!) and those who refrained to give beginners a chance.<\/p>\n<p>For more information about error handling in PowerShell, including the difference between terminating and non-terminating errors, see <a href=\"https:\/\/twitter.com\/MSH_Dave\">Dave Wyatt<\/a>&#8216;s awesome: <a href=\"https:\/\/devopscollective.gitbooks.io\/the-big-book-of-powershell-error-handling\/content\/manuscript\/introduction.html\">The Big Book of PowerShell Error Handling<\/a>. For help with the Try-Catch block, see <a href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkID=113444\">about_Try_Catch_Finally<\/a>. For help with PowerShell arithmetic, see <a href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkID=113208\">about_arithmetic_operators<\/a>.<\/p>\n<p>And, for some truly fun stuff with PowerShell arithmetic, see <a href=\"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2014\/09\/22\/fun-formatting-onespart-1-the-task\/\">Fun Formatting Ones, Part 1: The Task<\/a> and <a href=\"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2014\/09\/23\/fun-formatting-onespart-2-the-method\/\">Fun Formatting Ones, Part 2: The Method<\/a>, where we examine some really clever code by <a href=\"https:\/\/twitter.com\/dfinke\">Doug Finke<\/a>.<\/p>\n<p>Like this Friday PowerShell Puzzle? <a href=\"https:\/\/www.sapien.com\/blog\/?s=Friday+puzzle\">Find more puzzles here<\/a>. If you have a PowerShell puzzle suggestion, post it here or ping me on Twitter at <a href=\"https:\/\/twitter.com\/juneb_get_help\">@juneb_get_help<\/a>.<\/p>\n<p><span class=\"blog-half-page\"><i>June Blender is a technology evangelist at SAPIEN Technologies, Inc and a Microsoft Cloud &amp; Datacenter MVP. You can reach her at <a href=\"mailto:juneb@sapien.com\">juneb@sapien.com<\/a> or follow her on Twitter at <a href=\"https:\/\/twitter.com\/juneb_get_help\">@juneb_get_help<\/a>.<\/i><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>On Friday, January 6, 2017, I posted the following puzzle on Twitter and Facebook (here, too!). It shows a Try block that encloses an expression with an intentional error and a Catch block that writes an error. But, when you run it, the error doesn&#8217;t appear as designed. The error is supposed to say &#8216;Cannot [&hellip;]<\/p>\n","protected":false},"author":31,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[932,2,1143,1182,1055,25],"tags":[1184,1183,1187,1012,1186,1185],"class_list":["post-12935","post","type-post","status-publish","format-standard","hentry","category-beginners","category-general","category-powershell","category-puzzle","category-scripting","category-windows-powershell","tag-error-handling","tag-errors","tag-friday-puzzle","tag-ipowershell","tag-puzzle","tag-try-catch-finally"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/12935","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/users\/31"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/comments?post=12935"}],"version-history":[{"count":23,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/12935\/revisions"}],"predecessor-version":[{"id":13052,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/12935\/revisions\/13052"}],"wp:attachment":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/media?parent=12935"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/categories?post=12935"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/tags?post=12935"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}