1<?xml version="1.0" encoding="utf-8"?>
2<html xml:lang="en-US" lang="en-US">
3<head>
4    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5    <meta http-equiv="Content-Style-Type" content="text/css" />
6    <link rel="stylesheet" href="../../../css/page.css" type="text/css" />
7<title>File System: Error Handling</title>
8</head>
9<body>
10<h1>File System: Error Handling</h1>
11
12<h2>Table of Contents</h2>
13    <ul>
14<li><a href="#Summary">Overview</a></li>
15      <ul>
16<li><a href="#Summary_Result">Result Handling</a></li>
17<li><a href="#Summary_Error">Errors That Must Not Be Allowed to Occur in Retail Products</a></li>
18<li><a href="#Summary_Api">Functions for File and Directory Operations</a></li>
19      </ul>
20<li><a href="#Mounting">Handling Mount Errors</a></li>
21      <ul>
22<li><a href="#Mounting_RomArchive">ROM Archives</a></li>
23<li><a href="#Mounting_SaveDataArchive">Save Data Archives</a></li>
24<li><a href="#Mounting_ExtSaveDataArchive">Expanded Save Data Archives</a></li>
25      </ul>
26<li><a href="#FileAndDirectory">Handling Errors During File and Directory Operations</a></li>
27      <ul>
28<li><a href="#FileAndDirectory_RomArchive">ROM Archives</a></li>
29<li><a href="#FileAndDirectory_SaveDataArchive">Save Data Archives</a></li>
30<li><a href="#FileAndDirectory_ExtSaveDataArchive">Expanded Save Data Archives</a></li>
31      </ul>
32<li><a href="#History">Revision History</a></li>
33    </ul>
34
35<a name="Summary"><h2>Overview</h2></a>
36    <p>
37This page describes error handling for the file system.
38    </p>
39
40<a name="Summary_Result"><h3>Result Handling</h3></a>
41    <p>
42FS functions return many different types of <CODE>Result</CODE> values. These are handled by the following mechanism rather than one value at a time. The following example shows how to handle all errors belonging to the <CODE>NotFound</CODE> category.
43    </p>
44<pre>
45if(result &lt;= nn::fs::ResultNotFound())
46{
47    // This can catch nn::fs::ResultMediaNotFound as well.
48}
49</pre>
50    <p>
51The <CODE>Result</CODE> objects returned by FS functions are forbidden from using the arithmetic operators <CODE>==</CODE> or <CODE>!=</CODE>. Using these causes a build error. Also note that the following two examples are equivalent.
52    </p>
53<pre>
54if(nn::fs::ResultNotFound::Includes(result))
55{
56    ...
57}
58</pre>
59<pre>
60if(nn::fs::ResultNotFound() &gt;= result)
61{
62    ...
63}
64</pre>
65<p><font color="red">Do not directly handle any <CODE>Result</CODE> values that are not mentioned in the Function Reference Manual.</font></p>
66
67<a name="Summary_Error"><h3>Errors That Must Not Be Allowed to Occur in Retail Products</h3></a>
68    <p>
69The following <CODE>Result</CODE> values indicate errors that are caused by application bugs and other such problems. You must fix your program so that these do not occur in retail products.
70    </p>
71    <ul>
72<li><a href="../../../nn/fs/ResultOutOfResource/Overview.html"><CODE>ResultOutOfResource</CODE></a></li>
73<li><a href="../../../nn/fs/ResultAccessDenied/Overview.html"><CODE>ResultAccessDenied</CODE></a></li>
74<li><a href="../../../nn/fs/ResultInvalidArgument/Overview.html"><CODE>ResultInvalidArgument</CODE></a></li>
75<li><a href="../../../nn/fs/ResultNotInitialized/Overview.html"><CODE>ResultNotInitialized</CODE></a></li>
76<li><a href="../../../nn/fs/ResultAlreadyInitialized/Overview.html"><CODE>ResultAlreadyInitialized</CODE></a></li>
77<li><a href="../../../nn/fs/ResultUnsupportedOperation/Overview.html"><CODE>ResultUnsupportedOperation</CODE></a></li>
78    </ul>
79    <p>
80The <CODE>Result</CODE> values listed above may be caused by user operations or it may be impossible to get rid of them entirely during development. You must handle errors that can be caused by the user. Some functions may also specify errors that must not occur in retail products, even though the corresponding <CODE>Result</CODE> values are not among those listed above. For more information, see the documentation for each of these functions in the Function Reference Manual.
81    </p>
82
83<a name="Summary_Api"><h3>Functions for File and Directory Operations</h3></a>
84    <p>
85There are two types of functions used to perform file and directory operations: <CODE>Try</CODE> functions (which have the prefix <CODE>Try</CODE> added to the function name), and non-<CODE>Try</CODE> functions (which do not contain this prefix). <CODE>Try</CODE> functions return a <CODE>Result</CODE> as the return value, unless an fatal internal error occurs. Instead of returning <CODE>Results</CODE>, non-<CODE>Try</CODE> functions are implemented to display an error screen whenever an internal error returns, regardless of whether the error is fatal. Control does not return from the function in this case.<br />
86    </p>
87    <p>
88Internal errors never occur for ROM archives due to their characteristics. For ROM archives, implementation omissions in error handling can be avoided by using the non-<CODE>Try</CODE> functions. (During development, make sure to eliminate situations in which an error could occur because of an attempt to open a nonexistent file.)
89    </p>
90    <p>
91For archives other than ROM archives, you must always check for errors that can result from the user's operations. One typical example is removal of the Game Card by the user, which can lead to corrupted files. As a result, <CODE>Try</CODE> functions should always be used for error handling. Do not use non-<CODE>Try</CODE> functions because they can easily jump to error screens as a result of user operations.
92    </p>
93
94<a name="Mounting"><h2>Handling Mount Errors</h2></a>
95    <p>
96The following simplified C++ code provides guidelines for handling mount errors.
97    </p>
98
99<a name="Mounting_RomArchive"><h3>ROM Archives</h3></a> <code><pre>
100nn::Result result = nn::fs::MountRom();
101if(result.IsFailure())
102{
103    // A ROM archive never fails to be mounted. Any failure indicates an abnormal condition.
104    // NOTE: When developing an application, confirm that you are passing enough working memory as an argument.
105    //       Also check your Omakefile and RSF file to determine whether a ROMFS is created at build time.
106}
107</pre></code>
108
109<a name="Mounting_SaveDataArchive"><h3>Save Data Archives</h3></a> <code><pre>
110nn::Result result = nn::fs::MountSaveData();
111
112if(result.IsFailure())
113{
114    if(result &lt;= nn::fs::ResultNotFormatted())
115    {
116        // Formatting required.
117        // CAUSE: Unformatted save data region.
118        // NOTE: You must always format a save data region before mounting it for the first time.
119        result = nn::fs::FormatSaveData();
120    }
121    else if(result &lt;= nn::fs::ResultBadFormat())
122    {
123        // Formatting required.
124        // CAUSE: Invalid file format.
125        result = nn::fs::FormatSaveData();
126    }
127    else if(result &lt;= nn::fs::ResultVerificationFailed())
128    {
129        // Formatting required.
130        // CAUSE: Corrupted or tampered-with save data.
131        // NOTE: This state is never the result of user operations when there is automatic redundancy.
132        //       This error may be caused by user operations (such as removing a card or turning off the system while data is being written) when there is no automatic redundancy.
133        result = nn::fs::FormatSaveData();
134    }
135    else if(result &lt;= nn::fs::ResultOperationDenied())
136    {
137        // This error generally does not occur so no handling is required.
138        // NOTE: But nn::fs::ResultMediaAccessError is returned if the failure is due to a bad connection or other hardware factor.
139        //       In such cases, recovery may be possible by retrying, re-inserting the Game Card, restarting the system, or some other action.
140    }
141    else
142    {
143        // These are the only errors that could occur.
144    }
145
146    // Troubleshooting after formatting
147    if(result.IsFailure())
148    {
149        // The act of formatting save data never fails.
150        // NOTE: When developing your application, confirm that the maxFiles and maxDirectories arguments are not too big.
151        //       Also confirm that the content of the RSF file is correct.
152    }
153    else
154    {
155// Remount
156        result = nn::fs::MountSaveData();
157        if(result.IsFailure())
158        {
159            // A mount operation never fails immediately after data has been successfully formatted.
160        }
161    }
162}
163</pre></code>
164
165<a name="Mounting_ExtSaveDataArchive"><h3>Expanded Save Data Archives</h3></a> <code><pre>
166nn::Result result = nn::fs::MountExtSaveData();
167
168if(result.IsFailure())
169{
170    if(result &lt;= nn::fs::ResultNotFound())
171    {
172        if(result &lt;= nn::fs::ResultMediaNotFound())
173        {
174            // An SD Card has not been inserted.
175// Note: This error is also returned if the SD Card is damaged or if some medium other than an SD Card is inserted.
176//        In such cases, an insertion event registered by RegisterSdmcInsertedEvent is signaled.
177        }
178        else
179        {
180            // The specified expanded save data does not exist and must be created.
181            // NOTE: Confirm that the ID you specified is correct when developing your application.
182            result = nn::fs::CreateExtSaveData();
183        }
184    }
185    else if(result &lt;= nn::fs::ResultNotFormatted())
186    {
187        // You must recreate the expanded save data.
188        // CAUSE: Failed to create expanded save data.
189        result = nn::fs::DeleteExtSaveData();
190        if(result.IsSuccess())
191        {
192            result = nn::fs::CreateExtSaveData();
193        }
194    }
195    else if(result &lt;= nn::fs::ResultBadFormat())
196    {
197        // You must recreate the expanded save data.
198        // CAUSE: Invalid file format.
199        // NOTE: If not resolved, the SD Card must be formatted.
200        result = nn::fs::DeleteExtSaveData();
201        if(result.IsSuccess())
202        {
203            result = nn::fs::CreateExtSaveData();
204        }
205    }
206    else if(result &lt;= nn::fs::ResultVerificationFailed())
207    {
208        // You must recreate the expanded save data.
209        // CAUSE: Corrupted or tampered-with save data.
210        result = nn::fs::DeleteExtSaveData();
211        if(result.IsSuccess())
212        {
213            result = nn::fs::CreateExtSaveData();
214        }
215    }
216    else if(result &lt;= nn::fs::ResultArchiveInvalidated())
217    {
218        // An SD Card may have been removed while the archive was being mounted.
219        // Handle this just like nn::fs::ResultMediaNotFound().
220    }
221    else if(result &lt;= nn::fs::ResultOperationDenied())
222    {
223        if(result &lt;= nn::fs::ResultWriteProtected())
224        {
225            // The SD Card is write-protected.
226            // NOTE: This occurs if the data recovery sequence is run during a mount operation.
227        }
228        else if(result &lt;= nn::fs::ResultMediaAccessError())
229        {
230// This error is only returned when the cause is hardware-related, such as a loose connection.
231            //       In such cases, recovery may be possible by retrying, re-inserting the Game Card, restarting the system, or some other action.
232        }
233        else
234        {
235            // A mount operation is never denied for any reason other than those above.
236        }
237    }
238    else
239    {
240        // These are the only errors that could occur.
241    }
242
243    // Troubleshooting after data has been created
244    if(result.IsFailure())
245    {
246        if(result &lt;= nn::fs::ResultNotEnoughSpace())
247        {
248            // The SD Card does not have the necessary free space.
249        }
250        else if(result &lt;= nn::fs::ResultArchiveInvalidated())
251        {
252            // The SD Card may have been removed while data was being created.
253        }
254        else if(result &lt;= nn::fs::ResultNotFormatted())
255        {
256            // An error has occurred, interrupting the process of data creation.
257        }
258        else if(result &lt;= nn::fs::ResultOperationDenied())
259        {
260            if(result &lt;= nn::fs::ResultWriteProtected())
261            {
262                // The SD Card is write-protected.
263            }
264            else if(result &lt;= nn::fs::ResultMediaAccessError())
265            {
266// This error is only returned when the cause is hardware-related, such as a loose connection.
267                //       In such cases, recovery may be possible by retrying, re-inserting the Game Card, restarting the system, or some other action.
268            }
269            else
270            {
271                // This error will never be returned for any other reason.
272            }
273        }
274        else
275        {
276            // These are the only errors that could occur.
277            // NOTE: When developing your application, confirm that valid values are passed to iconData and iconDataSize.
278        }
279    }
280    else
281    {
282// Remount
283        result = nn::fs::MountExtSaveData();
284        if(result.IsFailure())
285        {
286            // As long as the SD Card is not removed, mount operations carried out immediately after the data is created will never fail.
287        }
288
289    }
290}
291</pre></code>
292
293<a name="FileAndDirectory"><h2>Handling Errors During File and Directory Operations</h2></a>
294    <p>
295The following simplified C++ code provides guidelines for handling errors during file and directory operations.
296    </p>
297    <p>
298There are two types of functions used to perform file and directory operations: <CODE>Try</CODE> functions (which have the prefix <CODE>Try</CODE> added to the function name), and non-<CODE>Try</CODE> functions (which do not contain this prefix). For details, see <a href="#Summary_Api">Functions for File and Directory Operations</a>.
299    </p>
300
301<a name="FileAndDirectory_RomArchive"><h3>ROM Archives</h3></a> <code><pre>
302nn::fs::XXX();
303// Because errors are handled internally by non-<CODE>Try</CODE> functions, you do not need to receive <CODE>Result</CODE> values.
304</pre>
305
306<a name="FileAndDirectory_SaveDataArchive"><h3>Save Data Archives</h3></a>
307<pre>
308result = nn::fs::TryXXX();
309
310if(result.IsFailure())
311{
312    if(result &lt;= nn::fs::ResultNotFound())
313    {
314        // The specified path does not exist.
315        // NOTE: This error is returned when creating a file or directory only if the problem  involves an incorrect archive name.
316        //       You do not need to handle this if, by design, it does not occur.
317    }
318    else if(result &lt;= nn::fs::ResultAlreadyExists())
319    {
320        // The specified path already exists.
321        // NOTE: This error is not returned when files and directories are deleted.
322        //       You do not need to handle this if, by design, it does not occur.
323    }
324    else if(result &lt;= nn::fs::ResultBadFormat())
325    {
326// Except for when data in backup memory is destroyed with the debugger,
327// this error is not returned when operating files and directories.
328// There is no need to handle this error in the product version.
329
330<s>// You must delete and recreate this file or directory.</s>
331<s>// CAUSE: Invalid file format.</s>
332<s>// NOTE: If this is not resolved, you must format the save data.</s>
333    }
334    else if(result &lt;= nn::fs::ResultVerificationFailed())
335    {
336        // You must delete and recreate this file or directory.
337        // CAUSE: Corrupted or tampered-with save data.
338        // NOTE: This state will never be caused by user operations (such as removing a card or turning off the system while data is being written) when there is automatic redundancy.
339        //       This error occurs even by user operations when there is no automatic redundancy.
340        //       If this is not resolved, you must format the save data.
341        // NOTE: This error is returned when reading a region that has never been written to.
342        // Be careful after executing the functions <CODE>nn::fs::TryCreateFile</CODE> and <CODE>nn::fs::FileStream::TrySetSize</CODE>.
343    }
344    else if(result &lt;= nn::fs::ResultOperationDenied())
345    {
346        // Access was denied for some reason.
347        // EXAMPLE: You attempted to delete a file that was open elsewhere.
348        //           You attempted to move a file or directory so that it would span archives.
349        //           You attempted to delete the root directory.
350        // NOTE: You do not need handling for the above situations if, by design, they will not occur.
351        //      But nn::fs::ResultMediaAccessError is returned if failure due to bad connection or other hardware factor.
352        //       In such cases, recovery may be possible by retrying, re-inserting the Game Card, restarting the system, or some other action.
353    }
354    else if(result &lt;= nn::fs::ResultNotEnoughSpace())
355    {
356        // There is no available space in the archive or on the storage media.
357        // NOTE: This error may occur when creating a file or directory, or changing the file size.
358        //       If this error occurs when you create a file, delete the file because it might be corrupted.
359        //       If this error occurs when you change the size of a file, the file may have grown to the maximum possible size.
360    }
361    else
362    {
363        // These are the only errors that could occur.
364    }
365}
366</pre></code>
367
368<a name="FileAndDirectory_ExtSaveDataArchive"><h3>Expanded Save Data Archives</h3></a> <code><pre>
369result = nn::fs::TryXXX();
370
371if(result.IsFailure())
372{
373    if(result &lt;= nn::fs::ResultNotFound())
374    {
375        if(result &lt;= nn::fs::ResultMediaNotFound())
376        {
377            // An SD Card has not been inserted.
378// Note: This error is also returned if the SD Card is damaged or if some medium other than an SD Card is inserted.
379//        In such cases, an insertion event registered by RegisterSdmcInsertedEvent is signaled.
380        }
381        else
382        {
383            // The specified path does not exist.
384// NOTE: This error is not returned when creating a file or directory if the problem does not involve an incorrect archive name.
385            // NOTE: Expanded save data can also be accessed from other applications,
386            // so handling is not required for this error.
387        }
388    }
389    else if(result &lt;= nn::fs::ResultAlreadyExists())
390    {
391        // The specified path already exists.
392        // NOTE: This error is not returned when files and directories are deleted.
393        // NOTE: Expanded save data can also be accessed from other applications,
394        // so handling is not required for this error.
395    }
396    else if(result &lt;= nn::fs::ResultBadFormat())
397    {
398        // You must delete and recreate this file or directory.
399        // CAUSE: Invalid file format.
400        // NOTE: If this is not resolved, you must format the SD Card.
401    }
402    else if(result &lt;= nn::fs::ResultVerificationFailed())
403    {
404        // You must delete and recreate this file or directory.
405        // CAUSE: Corrupted or tampered-with save data.
406        // NOTE: If this is not resolved, you need to recreate the expanded save data.
407// NOTE: This error is returned when loading a region that has never been written to.
408// Be careful after executing the <CODE>nn::fs::TryCreateFile</CODE> and <CODE>nn::fs::FileStream::TrySetSize</CODE> functions.
409    }
410    else if(result &lt;= nn::fs::ResultArchiveInvalidated())
411    {
412// You must remount the archive.
413        // CAUSE: The SD Card was removed, making the archive invalid.
414// NOTE: Close all open files, call the nn::fs::Unmount function, and then remount the archive.
415    }
416    else if(result &lt;= nn::fs::ResultOperationDenied())
417    {
418        if(result &lt;= nn::fs::ResultWriteProtected())
419        {
420            // The SD Card is write-locked.
421            // NOTE: This error occurs when you write to an SD Card. This does not occur when you simply open a file.
422        }
423        else if(result &lt;= nn::fs::ResultMediaAccessError())
424        {
425// This error is only returned when the cause is hardware-related, such as a loose connection.
426            //       In such cases, recovery may be possible by retrying, re-inserting the Game Card, restarting the system, or some other action.
427        }
428        else
429        {
430            // Access was denied for some reason other than those above.
431            // EXAMPLES: You attempted to write to a file that is read-only.
432            //           You attempted to delete a file that was open elsewhere.
433            //           You attempted to move a file or directory so that it would span archives.
434            //           You attempted to delete the root directory.
435            // NOTE: Expanded save data can also be accessed from other applications,
436            // so handling is not required for this error.
437        }
438    }
439    else if(result &lt;= nn::fs::ResultNotEnoughSpace())
440    {
441        // There is no available space in the archive or on the storage media.
442        // NOTE: This error may occur when creating a file or directory, or changing the file size.
443        //       If this error occurs when you create a file, delete the file because it might be corrupted.
444        //       If this error occurs when you change the size of a file, the file may have grown to the maximum possible size.
445    }
446    else
447    {
448        // These are the only errors that could occur.
449    }
450}
451</pre></code>
452
453<a name="History"><h2>Revision History</h2></a>
454    <div class="section">
455      <dl class="history">
456        <dt>2011/01/05</dt>
457        <dd>
458Changed the <CODE>Result</CODE> from <CODE>ResultMediaAccessError</CODE> to <CODE>ResultMediaNotFound</CODE> when a damaged SD Card is inserted.
459        </dd>
460        <dt>2010/12/14</dt>
461        <dd>
462Added errors that must not be allowed to occur in retail products.
463        </dd>
464        <dd>
465Added <CODE>ResultNotFormatted</CODE> and <CODE>ResultArchiveInvalidated</CODE> to error handling when expanded save data is created.
466        </dd>
467        <dt>2010/12/13</dt>
468        <dd>
469Split up error handling for file and directory operations by archive type.
470        </dd>
471        <dd>
472Changed how <CODE>ResultOperationDenied</CODE> is handled when expanded save data is mounted.
473        </dd>
474        <dt>2010/12/09</dt>
475        <dd>
476Added <B>Functions for File and Directory Operations</B>.
477        </dd>
478        <dt>2010/12/02</dt>
479        <dd>
480Removed <CODE>ResultNotFound</CODE> from save data error handling.
481        </dd>
482        <dt>2010/11/31</dt>
483        <dd>
484Added <CODE>ResultNotEnoughSpace</CODE> to the errors occurring during file operations.
485        </dd>
486        <dt>2010/11/25</dt>
487        <dd>
488Added <CODE>ResultNotFormatted</CODE> to error handling for expanded save data.
489        </dd>
490        <dt>2010/11/13</dt>
491        <dd>
492Initial version.
493        </dd>
494      </dl>
495    </div>
496
497<hr><p>CONFIDENTIAL</p></body>
498</html>
499