{"id":106176,"date":"2022-01-19T07:00:00","date_gmt":"2022-01-19T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=106176"},"modified":"2022-01-18T21:25:41","modified_gmt":"2022-01-19T05:25:41","slug":"20220119-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20220119-00\/?p=106176","title":{"rendered":"The error code you get might not be the one you want"},"content":{"rendered":"<p>A customer was following the instructions on how to <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/uwp\/launch-resume\/create-and-register-a-winmain-background-task\"> create a register a background task from a Win32 desktop app<\/a>, but they found that the sample code failed with an exception:<\/p>\n<pre>bool taskRegistered = false;\r\nstd::wstring sampleTaskName = L\"SampleTask\";\r\nauto allTasks = BackgroundTaskRegistration::AllTasks();\r\n\/\/                                          ^^^^^^^^^ exception\r\n\r\nfor (auto const&amp; task : allTasks)\r\n{\r\n    if (task.Value().Name() == sampleTaskName)\r\n    {\r\n        taskRegistered = true;\r\n        break;\r\n    }\r\n}\r\n\r\n\/\/ The code in the next step goes here.\r\n<\/pre>\n<p>The code for the exception was <code>ERROR_<wbr \/>NOT_<wbr \/>FOUND<\/code> (&#8220;Element not found&#8221;).<\/p>\n<p>Which is weird. I mean, I&#8217;m asking for all of the tasks, and you&#8217;re telling me &#8220;I couldn&#8217;t find any&#8221; and throwing an exception? Shouldn&#8217;t it just be returning an empty collection if there aren&#8217;t any existing tasks?<\/p>\n<p>Indeed, it does return an empty collection if there aren&#8217;t any existing tasks. The error code is not telling you that there are no existing tasks. The error code is telling you that your app doesn&#8217;t have a packaged app identity (probably because it&#8217;s not packaged at all). The thing that couldn&#8217;t be find was the package identity.<\/p>\n<p>Okay, sure, but shouldn&#8217;t the error code have been <code>APPMODEL_<wbr \/>ERROR_<wbr \/>NO_<wbr \/>PACKAGE<\/code> (&#8220;The process has no package identity&#8221;)?<\/p>\n<p>Error codes are one of the places where abstractions are leakiest, because errors merely propagate out from their point of origin, and the context in which the error is generated may not be anything the application developer is aware of.<\/p>\n<p>In this case, what&#8217;s happening is that the request is going down through the background task infrastructure. The request goes out to a server, and the server tries to find out who is calling. There&#8217;s an internal function for identifying the caller, and it works by looking for information inside the caller&#8217;s token.<\/p>\n<p>If the caller does not have package identity, then the &#8220;Find the thing in a token&#8221; function returns <code>ERROR_<wbr \/>NOT_<wbr \/>FOUND<\/code> because &#8220;I couldn&#8217;t find the thing you asked about.&#8221; That low-level function doesn&#8217;t know <i>why<\/i> the caller is asking for the thing. It is just reporting the simple fact that the thing the caller wants is not present.<\/p>\n<p>As the error propagates out of the system, nobody thinks to say &#8220;Let me transform that generic <code>ERROR_<wbr \/>NOT_<wbr \/>FOUND<\/code> into this other more specific-sounding error code,&#8221; so what comes out is a generic <code>ERROR_<wbr \/>NOT_<wbr \/>FOUND<\/code>.<\/p>\n<p>Which is technically correct, but in the context of something you the application developer are probably unaware of.<\/p>\n<p>As a general rule, <code>HRESULT<\/code>s and Win32 error codes are like that. The actual numeric value is often descriptive of a low-level situation far removed from the high-level operation the application requested. In the absence of specific documentation to the contrary, the only stable thing about <code>HRESULT<\/code> and Win32 error codes is whether or not they succeeded. If they report failure, you might be able to use the specific value to help guide debugging, but it&#8217;s not usually expected that they be specific with pinpoint accuracy.<\/p>\n<p>This is one reason why the Windows Runtime design guidelines recommend that failures that application are expected to <a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20170307-00\/?p=95675\"> reason over<\/a> should be reported with a specific enumeration, rather than using <code>HRESULT<\/code>s. This makes the stability boundary explicit: The system will make sure that the errors map to one of the values of the enumeration, even if under the covers they are aggregated from multiple sources. It is the system&#8217;s responsibility to take those failures and convert them to something that the application can rely on not changing.<\/p>\n<p><b>Bonus chatter<\/b>: As far as I can tell, the <code>APPMODEL_<wbr \/>ERROR_<wbr \/>NO_<wbr \/>PACKAGE<\/code> error code is used only by a handful of functions in <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/appmodel\/\"> <code>appmodel.h<\/code><\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Some error codes are contractual, but most aren&#8217;t.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-106176","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Some error codes are contractual, but most aren&#8217;t.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/106176","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=106176"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/106176\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=106176"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=106176"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=106176"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}