]> git.proxmox.com Git - libgit2.git/blame - docs/error-handling.md
install as examples
[libgit2.git] / docs / error-handling.md
CommitLineData
845f8314
VM
1Error reporting in libgit2
2==========================
3
aa94acf0
RB
4Libgit2 tries to follow the POSIX style: functions return an `int` value
5with 0 (zero) indicating success and negative values indicating an error.
6There are specific negative error codes for each "expected failure"
7(e.g. `GIT_ENOTFOUND` for files that take a path which might be missing)
8and a generic error code (-1) for all critical or non-specific failures
9(e.g. running out of memory or system corruption).
10
11When a negative value is returned, an error message is also set. The
ac3d33df 12message can be accessed via the `git_error_last` function which will return a
aa94acf0
RB
13pointer to a `git_error` structure containing the error message text and
14the class of error (i.e. what part of the library generated the error).
15
16For instance: An object lookup by SHA prefix (`git_object_lookup_prefix`)
17has two expected failure cases: the SHA is not found at all which returns
18`GIT_ENOTFOUND` or the SHA prefix is ambiguous (i.e. two or more objects
19share the prefix) which returns `GIT_EAMBIGUOUS`. There are any number of
20critical failures (such as a packfile being corrupted, a loose object
21having the wrong access permissions, etc.) all of which will return -1.
22When the object lookup is successful, it will return 0.
23
24If libgit2 was compiled with threads enabled (`-DTHREADSAFE=ON` when using
25CMake), then the error message will be kept in thread-local storage, so it
26will not be modified by other threads. If threads are not enabled, then
27the error message is in global data.
28
29All of the error return codes, the `git_error` type, the error access
30functions, and the error classes are defined in `include/git2/errors.h`.
31See the documentation there for details on the APIs for accessing,
32clearing, and even setting error codes.
33
34When writing libgit2 code, please be smart and conservative when returning
35error codes. Functions usually have a maximum of two or three "expected
36errors" and in most cases only one. If you feel there are more possible
37expected error scenarios, then the API you are writing may be at too high
38a level for core libgit2.
39
40Example usage
41-------------
42
43When using libgit2, you will typically capture the return value from
44functions using an `int` variable and check to see if it is negative.
45When that happens, you can, if you wish, look at the specific value or
46look at the error message that was generated.
845f8314
VM
47
48~~~c
845f8314 49{
aa94acf0
RB
50 git_repository *repo;
51 int error = git_repository_open(&repo, "path/to/repo");
845f8314 52
aa94acf0 53 if (error < 0) {
ac3d33df 54 fprintf(stderr, "Could not open repository: %s\n", git_error_last()->message);
aa94acf0
RB
55 exit(1);
56 }
845f8314 57
aa94acf0 58 ... use `repo` here ...
845f8314 59
aa94acf0 60 git_repository_free(repo); /* void function - no error return code */
845f8314
VM
61}
62~~~
63
aa94acf0
RB
64Some of the error return values do have meaning. Optionally, you can look
65at the specific error values to decide what to do.
66
67~~~c
68{
69 git_repository *repo;
70 const char *path = "path/to/repo";
71 int error = git_repository_open(&repo, path);
72
73 if (error < 0) {
74 if (error == GIT_ENOTFOUND)
75 fprintf(stderr, "Could not find repository at path '%s'\n", path);
76 else
77 fprintf(stderr, "Unable to open repository: %s\n",
ac3d33df 78 git_error_last()->message);
aa94acf0
RB
79 exit(1);
80 }
845f8314 81
aa94acf0
RB
82 ... happy ...
83}
84~~~
845f8314 85
aa94acf0
RB
86Some of the higher-level language bindings may use a range of information
87from libgit2 to convert error return codes into exceptions, including the
88specific error return codes and even the class of error and the error
ac3d33df 89message returned by `git_error_last`, but the full range of that logic is
aa94acf0 90beyond the scope of this document.
845f8314 91
aa94acf0
RB
92Example internal implementation
93-------------------------------
845f8314 94
aa94acf0
RB
95Internally, libgit2 detects error scenarios, records error messages, and
96returns error values. Errors from low-level functions are generally
97passed upwards (unless the higher level can either handle the error or
98wants to translate the error into something more meaningful).
845f8314 99
aa94acf0
RB
100~~~c
101int git_repository_open(git_repository **repository, const char *path)
102{
103 /* perform some logic to open the repository */
104 if (p_exists(path) < 0) {
ac3d33df 105 git_error_set(GIT_ERROR_REPOSITORY, "The path '%s' doesn't exist", path);
aa94acf0
RB
106 return GIT_ENOTFOUND;
107 }
845f8314 108
aa94acf0
RB
109 ...
110}
111~~~
845f8314 112
ac3d33df
JK
113Note that some error codes have been defined with a specific meaning in the
114context of callbacks:
115- `GIT_EUSER` provides a way to bubble up a non libgit2-related failure, which
116 allows it to be preserved all the way up to the initial function call (a `git_cred`
117 setup trying to access an unavailable LDAP server for instance).
118- `GIT_EPASSTHROUGH` provides a way to tell libgit2 that it should behave as if
119 no callback was provided. This is of special interest to bindings, which would
120 always provide a C function as a "trampoline", and decide at runtime what to do.
121
aa94acf0
RB
122The public error API
123--------------------
845f8314 124
ac3d33df 125- `const git_error *git_error_last(void)`: The main function used to look up
aa94acf0
RB
126 the last error. This may return NULL if no error has occurred.
127 Otherwise this should return a `git_error` object indicating the class
128 of error and the error message that was generated by the library.
ac3d33df
JK
129 Do not use this function unless the prior call to a libgit2 API
130 returned an error, as it can otherwise give misleading results.
131 libgit2's error strings are not cleared aggressively,
132 and this function may return an error string that reflects a prior error,
133 possibly even reflecting internal state.
aa94acf0
RB
134
135 The last error is stored in thread-local storage when libgit2 is
136 compiled with thread support, so you do not have to worry about another
137 thread overwriting the value. When thread support is off, the last
138 error is a global value.
139
140 _Note_ There are some known bugs in the library where this may return
141 NULL even when an error code was generated. Please report these as
142 bugs, but in the meantime, please code defensively and check for NULL
143 when calling this function.
144
ac3d33df 145- `void git_error_clear(void)`: This function clears the last error. The
aa94acf0
RB
146 library will call this when an error is generated by low level function
147 and the higher level function handles the error.
148
149 _Note_ There are some known bugs in the library where a low level
150 function's error message is not cleared by higher level code that
151 handles the error and returns zero. Please report these as bugs, but in
152 the meantime, a zero return value from a libgit2 API does not guarantee
ac3d33df 153 that `git_error_last()` will return NULL.
aa94acf0 154
ac3d33df 155- `void git_error_set(int error_class, const char *message)`: This
aa94acf0
RB
156 function can be used when writing a custom backend module to set the
157 libgit2 error message. See the documentation on this function for its
158 use. Normal usage of libgit2 will probably never need to call this API.
159
ac3d33df 160- `void git_error_set_oom(void)`: This is a standard function for reporting
aa94acf0
RB
161 an out-of-memory error. It is written in a manner that it doesn't have
162 to allocate any extra memory in order to record the error, so this is
163 the best way to report that scenario.
164
165Deviations from the standard
166----------------------------
167
168There are some public functions that do not return `int` values. There
169are two primary cases:
170
171* `void` return values: If a function has a `void` return, then it will
172 never fail. This primary will be used for object destructors.
173
174* `git_xyz *` return values: These are simple accessor functions where the
175 only meaningful error would typically be looking something up by index
176 and having the index be out of bounds. In those cases, the function
177 will typically return NULL.
178
179* Boolean return values: There are some cases where a function cannot fail
180 and wants to return a boolean value. In those cases, we try to return 1
181 for true and 0 for false. These cases are rare and the return value for
182 the function should probably be an `unsigned int` to denote these cases.
183 If you find an exception, please open an issue and let's fix it.
184
185There are a few other exceptions to these rules here and there in the
186library, but those are extremely rare and should probably be converted
187over to other to more standard patterns for usage. Feel free to open
188issues pointing these out.
189
190There are some known bugs in the library where some functions may return a
191negative value but not set an error message and some other functions may
192return zero (no error) and yet leave an error message set. Please report
193these cases as issues and they will be fixed. In the meanwhile, please
ac3d33df
JK
194code defensively, checking that the return value of `git_error_last` is not
195NULL before using it, and not relying on `git_error_last` to return NULL when
aa94acf0
RB
196a function returns 0 for success.
197
198The internal error API
199----------------------
845f8314 200
ac3d33df 201- `void git_error_set(int error_class, const char *fmt, ...)`: This is the
aa94acf0 202 main internal function for setting an error. It works like `printf` to
ac3d33df 203 format the error message. See the notes of `git_error_set_str` for a
aa94acf0 204 general description of how error messages are stored (and also about
ac3d33df 205 special handling for `error_class` of `GIT_ERROR_OS`).
845f8314
VM
206
207Writing error messages
208----------------------
209
210Here are some guidelines when writing error messages:
211
aa94acf0
RB
212- Use proper English, and an impersonal or past tenses: *The given path
213 does not exist*, *Failed to lookup object in ODB*
845f8314 214
aa94acf0
RB
215- Use short, direct and objective messages. **One line, max**. libgit2 is
216 a low level library: think that all the messages reported will be thrown
217 as Ruby or Python exceptions. Think how long are common exception
218 messages in those languages.
845f8314 219
aa94acf0
RB
220- **Do not add redundant information to the error message**, specially
221 information that can be inferred from the context.
845f8314 222
aa94acf0
RB
223 E.g. in `git_repository_open`, do not report a message like "Failed to
224 open repository: path not found". Somebody is calling that
225 function. If it fails, they already know that the repository failed to
226 open!
845f8314
VM
227
228General guidelines for error reporting
229--------------------------------------
230
aa94acf0
RB
231- Libgit2 does not handle programming errors with these
232 functions. Programming errors are `assert`ed, and when their source is
233 internal, fixed as soon as possible. This is C, people.
845f8314 234
aa94acf0
RB
235 Example of programming errors that would **not** be handled: passing
236 NULL to a function that expects a valid pointer; passing a `git_tree`
237 to a function that expects a `git_commit`. All these cases need to be
238 identified with `assert` and fixed asap.
845f8314 239
aa94acf0
RB
240 Example of a runtime error: failing to parse a `git_tree` because it
241 contains invalid data. Failing to open a file because it doesn't exist
242 on disk. These errors are handled, a meaningful error message is set,
243 and an error code is returned.
845f8314 244
aa94acf0
RB
245- In general, *do not* try to overwrite errors internally and *do*
246 propagate error codes from lower level functions to the higher level.
247 There are some cases where propagating an error code will be more
248 confusing rather than less, so there are some exceptions to this rule,
249 but the default behavior should be to simply clean up and pass the error
250 on up to the caller.
845f8314 251
aa94acf0 252 **WRONG**
845f8314
VM
253
254 ~~~c
aa94acf0
RB
255 int git_commit_parent(...)
256 {
257 ...
845f8314 258
aa94acf0 259 if (git_commit_lookup(parent, repo, parent_id) < 0) {
ac3d33df 260 git_error_set(GIT_ERROR_COMMIT, "Overwrite lookup error message");
aa94acf0
RB
261 return -1; /* mask error code */
262 }
845f8314 263
aa94acf0
RB
264 ...
265 }
845f8314
VM
266 ~~~
267
aa94acf0 268 **RIGHT**
845f8314
VM
269
270 ~~~c
aa94acf0 271 int git_commit_parent(...)
845f8314 272 {
aa94acf0 273 ...
845f8314 274
aa94acf0
RB
275 error = git_commit_lookup(parent, repo, parent_id);
276 if (error < 0) {
277 /* cleanup intermediate objects if necessary */
278 /* leave error message and propagate error code */
279 return error;
280 }
845f8314 281
aa94acf0
RB
282 ...
283 }
284 ~~~