| 1 | ---
 | 
| 2 | default_highlighter: oils-sh
 | 
| 3 | ---
 | 
| 4 | 
 | 
| 5 | Guide to YSH Error Handling
 | 
| 6 | ===========================
 | 
| 7 | 
 | 
| 8 | There are just a few concepts to know:
 | 
| 9 | 
 | 
| 10 | - [error][] builtin - "Throw" an error, with a custom message, error code, and
 | 
| 11 |   other properties.
 | 
| 12 | - [try][] builtin - Run a block, and set the [_error][] register to a `Dict`.
 | 
| 13 |   - `_error.code` will be `0` on success, or non-zero if an error is thrown in
 | 
| 14 |     the block.
 | 
| 15 | - [failed][] builtin - A handy shortcut to test for a non-zero error code.
 | 
| 16 | 
 | 
| 17 | [try]: ref/chap-builtin-cmd.html#try
 | 
| 18 | [_error]: ref/chap-special-var.html#_error
 | 
| 19 | 
 | 
| 20 | [error]: ref/chap-builtin-cmd.html#error
 | 
| 21 | [failed]: ref/chap-builtin-cmd.html#failed
 | 
| 22 | 
 | 
| 23 | <div id="toc">
 | 
| 24 | </div>
 | 
| 25 | 
 | 
| 26 | ## Examples
 | 
| 27 | 
 | 
| 28 | ### Handle command and expression errors with `try`
 | 
| 29 | 
 | 
| 30 | Here's the most basic form:
 | 
| 31 | 
 | 
| 32 |     try {
 | 
| 33 |       ls /zz
 | 
| 34 |     }
 | 
| 35 |     if (_error.code !== 0) {
 | 
| 36 |       echo "ls failed with $[_error.code]"
 | 
| 37 |     } 
 | 
| 38 |     # => ls failed with error 2
 | 
| 39 | 
 | 
| 40 | 
 | 
| 41 | ### The `failed` builtin is a shortcut
 | 
| 42 | 
 | 
| 43 | Instead of writing `if (_error.code !== 0)`, you can write `if failed`:
 | 
| 44 | 
 | 
| 45 |     if failed {
 | 
| 46 |       echo "ls failed with $[_error.code]"
 | 
| 47 |     } 
 | 
| 48 | 
 | 
| 49 | This saves you 7 punctuation characters: `( _ . !== )`
 | 
| 50 | 
 | 
| 51 | ### Use a `case` statement if it's not just pass/fail
 | 
| 52 | 
 | 
| 53 | Sometimes it's nicer to use `case` rather than `if`:
 | 
| 54 | 
 | 
| 55 |     try {
 | 
| 56 |       grep '[0-9]+' foo.txt
 | 
| 57 |     }
 | 
| 58 |     case (_error.code) {
 | 
| 59 |       (0)    { echo 'found' }
 | 
| 60 |       (1)    { echo 'not found' }
 | 
| 61 |       (else) { echo 'error invoking grep' }
 | 
| 62 |     }
 | 
| 63 | 
 | 
| 64 | ### Error may have more attributes, like `_error.message`
 | 
| 65 | 
 | 
| 66 |     try {
 | 
| 67 |       var x = fromJson('{')
 | 
| 68 |     }
 | 
| 69 |     if failed {
 | 
| 70 |       echo "JSON failure: $[_error.message]"
 | 
| 71 |     }
 | 
| 72 |     # => JSON failure: expected string, got EOF
 | 
| 73 | 
 | 
| 74 | ### The `error` builtin throws custom errors
 | 
| 75 | 
 | 
| 76 | A non-zero exit code results in a simple shell-style error:
 | 
| 77 | 
 | 
| 78 |     proc simple-failure {
 | 
| 79 |       return 2
 | 
| 80 |     }
 | 
| 81 | 
 | 
| 82 |     try {
 | 
| 83 |       simple-failure
 | 
| 84 |     }
 | 
| 85 |     echo "status is $[_error.code]"
 | 
| 86 |     # => status is 2
 | 
| 87 | 
 | 
| 88 | The `error` builtin is more informative:
 | 
| 89 | 
 | 
| 90 |     proc better-failure {
 | 
| 91 |       error 'Custom message' (code=99, foo='zz')
 | 
| 92 |     }
 | 
| 93 | 
 | 
| 94 |     try {
 | 
| 95 |       better-failure
 | 
| 96 |     }
 | 
| 97 |     echo "$[_error.code] $[_error.message] foo=$[_error.foo]"
 | 
| 98 |     # => 99 Custom message foo=zz"
 | 
| 99 | 
 | 
| 100 | ## Related
 | 
| 101 | 
 | 
| 102 | - [YSH vs. Shell Idioms > Error Handling](idioms.html#error-handling)
 | 
| 103 | - [YSH Fixes Shell's Error Handling (`errexit`)](error-handling.html) - Long
 | 
| 104 |   design doc.
 | 
| 105 | 
 | 
| 106 | 
 |