Fossil SCM

fossil-scm / www / json-api / conventions.md
1
# JSON API: General Conventions
2
([⬑JSON API Index](index.md))
3
4
Jump to:
5
6
* [JSON Property Naming](#property-names)
7
* [HTTP GET Requests](#http-get)
8
* [HTTP POST Requests](#http-post)
9
* [POST Request Envelope](#request-envelope)
10
* [Request Parameter Data Types](#request-param-types)
11
* [Response Envelope](#response-envelope)
12
* [HTTP Response Headers](#http-response-header)
13
* [CLI vs. HTTP Mode](#cli-vs-http)
14
* [Simulating POSTed data](#simulating-post-data)
15
* [Indentation/Formatting of JSON Output](#json-indentation)
16
* [JSONP](#jsonp)
17
* [API Result Codes](#result-codes)
18
19
---
20
21
<a id="property-names"></a>
22
# JSON Property Naming
23
24
Since most JSON usage conventionally happens in JavaScript
25
environments, this API has (without an explicit decision ever having
26
been made) adopted the ubiquitous JavaScript convention of
27
`camelCaseWithStartingLower` for naming properties in JSON objects.
28
29
<a id="http-get"></a>
30
# HTTP GET Requests
31
32
Many (if not most) requests can be made via simple GET requests, e.g. we
33
*could* use any of the following patterns for a hypothetical JSON-format
34
timeline:
35
36
- `https://..../timeline/json`
37
- `/timeline?format=json`
38
- `/timeline?json=1`
39
- `/timeline.json`
40
- `/json/timeline?...options...`
41
42
The API settled on the `/json/...` convention, primarily because it
43
simplifies dispatching and argument-handling logic compared to the
44
`/[.../]foo.json` approach. Using `/json/...` allows us to unify that
45
logic for all JSON sub-commands, for both CLI and HTTP modes.
46
47
<a id="http-post"></a>
48
# HTTP Post Requests
49
50
Certain requests, mainly things like editing checkin messages and
51
committing new files entirely, require POST data. This is fundamentally
52
very simple to do - clients post plain/unencoded JSON using a common
53
wrapper envelope which contains the request-specific data to submit as
54
well as some request-independent information (like authentication data).
55
56
<a id="request-envelope"></a>
57
## POST Request Envelope
58
59
POST requests are sent to the same URL as their GET counterpart (if any,
60
else their own path), and are sent as plain-text/unencoded JSON wrapped
61
in a common request envelope with the following properties:
62
63
- `requestId`: Optional arbitrary JSON value, not used by fossil, but
64
returned as-is in responses.
65
- `command`: Provides a secondary mechanism for specifying which JSON
66
command should be run. A request path of /json/foo/bar is equivalent
67
to a request with path=/json and command=foo/bar. Note that subpaths
68
do not work this way. e.g. path=/json/foo, command=bar will not
69
work, but path=/json, command=foo/bar will. This option is
70
particularly useful when generating JSON for piping in to CLI mode,
71
but it also has some response-dispatching uses on the client side.
72
- `authToken`: Authentication token. Created by a login
73
request. Determines what access rights the user has, and any given
74
request may require specific rights. In principle this is required
75
by any request which needs non-guest privileges, but cookie-aware
76
clients do not manually need to track this (it is managed as a
77
cookie by the agent/browser).
78
- Note that when accessing fossil over a local server instance
79
which was started with the `--localauth` flag, the `authToken`
80
will be ignored and need not be sent with any requests. The user
81
will automatically be given full privileges, as if they were
82
using CLI mode.
83
- `payload`: Command-specific parameters. Most can optionally come in
84
via GET parameters, but those taking complex structures expect them
85
to be placed here.
86
- `indent`: Optionally specifies indentation for the output. 0=no
87
indention. 1=a single TAB character for each level of
88
indentation. >1 means that many spaces per level. e.g. indent=7
89
means to indent 7 spaces per object/array depth level. cson also
90
supports other flags for fine-tuning the output spacing, and adding
91
them to this interface might be interesting at some
92
point. e.g. whether or not to add a newline to the output. CLI mode
93
adds extra indentation by default, whereas CGI/server modes produce
94
unindented output by default.
95
- `jsonp`: Optional String (client function name). Requests which
96
include this will be returned with `Content-Type
97
application/javascript` and will be wrapped up in a function call
98
using the given name. e.g. if `jsonp=foo` then the result would look like:\
99
`foo( {...the response envelope...} )`
100
101
The API allows most of those (normally all but the payload) to come in
102
as either GET parameters or properties of the top-level POSTed request
103
JSON envelope, with GET taking priority over POST. (Reminder to self: we
104
could potentially also use values from cookies. Fossil currently only
105
uses 1 cookie (the login token), and I'd prefer to keep it that way.)
106
107
POST requests without such an envelope will be rejected, generating a
108
Fossil/JSON error response (as opposed to an HTTP error response). GET
109
requests, by definition, never have an envelope.
110
111
POSTed client requests *must* send a Content-Type header of either
112
`application/json` , `application/javascript`, or `text/plain`, or the
113
JSON-handling code will never see the POST data. The POST handler
114
optimistically assumes that type `text/plain` "might be JSON", since
115
`application/json` is a newer convention which many existing clients
116
do not use (as of the time these docs were written, back in 2011).
117
118
## POST Envelope vs. `POST.payload`
119
120
121
When this document refers to POST data, it is referring to top-level
122
object in JSON-format POSTed input data. When we say `POST.payload` we
123
refer to the "payload" property of the POST data. While fossil's core
124
handles *form-urlencoded* POST data, if such data is sent in then
125
parsing it as JSON cannot succeed, which means that (at worst) the
126
JSON-mode bits will "not see" any POST data. Data POSTed to the JSON API
127
must be sent non-form-urlencoded (i.e. as plain text).
128
129
Framework-level configuration options are always set via the top-level
130
POST envelope object or GET parameters. Request-specific options are set
131
either in `POST.payload` or GET parameters (though the former is required
132
in some cases). Here is an example which demonstrates the possibly
133
not-so-obvious difference between the two types of options (framework
134
vs. request-specific):
135
136
```json
137
{
138
"requestId":"my request", // standard envelope property (optional)
139
"command": "timeline/wiki", // also standard
140
"indent":2, // output indention is a framework-level option
141
"payload":{ // *anything* in the payload is request-specific
142
"limit":1
143
}
144
}
145
```
146
147
When a given parameter is set in two places, e.g. GET and POST, or
148
POST-from-a-file and CLI parameters, which one takes precedence
149
depends on the concrete command handler (and may be unspecified). Most
150
will give precedence to CLI and GET parameters, but POSTed values are
151
technically preferred for non-string data because no additional "type
152
guessing" or string-to-whatever conversion has to be made (GET/CLI
153
parameters are *always* strings, even if they look like a number or
154
boolean).
155
156
157
<a id="request-param-types"></a>
158
# Request Parameter Data Types
159
160
When parameters are sent in the form of GET or CLI arguments, they are
161
inherently strings. When they come in from JSON they keep their full
162
type (boolean, number, etc.). All parameters in this API specify what
163
*type* (or types) they must (or may) be. For strings, there is no
164
internal conversion/interpretation needed for GET- or CLI-provided
165
parameters, but for other types we sometimes have to convert strings to
166
other atomic types. This section describes how those string-to-whatever
167
conversions behave.
168
169
No higher-level constructs, e.g. JSON **arrays** or **objects**, are
170
accepted in string form. Such parameters must be set in the POST
171
envelope or payload, as specified by the specific API.
172
173
This API does not currently use any **floating-point** parameters, but
174
does return floating-point results in a couple of places.
175
176
For **integer** parameters we use a conventional string-to-int algorithm
177
and assume base 10 (analog to atoi(3)). The API may err on the side of
178
usability when given technically invalid values. e.g. "123abc" will
179
likely be interpreted as the integer 123. No APIs currently rely on
180
integer parameters with more than 32 bits (signedness is call-dependent
181
but few, if any, use negative values).
182
183
**Boolean** parameters are a bit schizophrenic...
184
185
In **CLI mode**, boolean flags do not have a value, per se, and thus
186
require no string-to-bool conversion. e.g.
187
`fossil foo -aBoolOpt -non-bool-opt value`.
188
189
Those which arrive as strings via **GET parameters** treat any of the
190
following as true: a string starting with a character in the set
191
`[1-9tT]`. All other string values are considered to be false for this
192
purpose.
193
194
Those which are part of the **POST data** are normally (but not always -
195
it depends on the exact context) evaluated as the equivalent of
196
JavaScript booleans. e.g. if we have `POST.envelope.foo="f"`, and evaluate
197
it as a JSON boolean (as opposed to a string-to-bool conversion), the
198
result will be true because the underlying JSON API follows JavaScript
199
semantics for any-type-to-bool conversions. As long as clients always
200
send "proper" booleans in their POST data, the difference between
201
GET/CLI-provided booleans should never concern them.
202
203
TODO: consider changing the GET-value-to-bool semantics to match the JS
204
semantics, for consistency (within the JSON API at least, but that might
205
cause inconsistencies vis-a-vis the HTML interface).
206
207
<a id="response-envelope"></a>
208
# Response Envelope
209
210
Every response comes in the form of an HTTP response or (in CLI mode)
211
JSON sent to stdout. The body of the response is a JSON object following
212
a common envelope format. The envelope has the following properties:
213
214
215
- `fossil`: Fossil server version string. This property is basically
216
"the official response envelope marker" - if it is set, clients can
217
"probably safely assume" that the object indeed came from one of the
218
Fossil/JSON APIs. This API never creates responses which do not
219
contain this property.
220
- `requestId`: Only set if the request contained it, and then it is
221
echoed back to the caller as-is. This can be used to determine
222
(client-side) which request a given response is coming in for
223
(assuming multiple asynchronous requests are pending). In practice
224
this generally isn’t needed because response handling tends to be
225
done by closures associated with the original request object (at
226
least in JavaScript code). In languages without closures it might
227
have some use. It may be any legal JSON value - it need not be
228
confined to a string or number.
229
- `resultCode`: Standardized result code string in the form
230
`FOSSIL-####`. Only error responses contain a `resultCode`.
231
- `resultText`: Possibly a descriptive string, possibly
232
empty. Supplements the resultCode, but can also be set on success
233
responses (but normally isn't). Clients must not rely on any
234
specific values being set here.
235
- `payload`: Request-specific response payload (data type/structure is
236
request-specific). The payload is never set for error responses,
237
only for success responses (and only those which actually have a
238
payload - not all do).
239
- `timestamp`: Response timestamp (GMT Unix Epoch). We use seconds
240
precision because I did not know at the time that Fossil actually
241
records millisecond precision.
242
- `payloadVersion`: Not initially needed, but reserved for future use
243
in maintaining version compatibility when the format of a given
244
response type's payload changes. If needed, the "first version"
245
value is assumed to be 0, for semantic [near-]compatibility with the
246
undefined value clients see when this property is not set.
247
- `command`: Normalized form of the command being run. It consists of
248
the "command" (non-argument) parts of the request path (or CLI
249
positional arguments), excluding the initial "/json/" part. e.g. the
250
"command" part of "/json/timeline/checkin?a=b" (CLI: json timeline
251
checkin...) is "timeline/checkin" (both in CLI and HTTP modes).
252
- `apiVersion`: Not yet used, but reserved for a numeric value which
253
represents the JSON API's version (which can be used to determine if
254
it has a given feature or not). This will not be implemented until
255
it's needed.
256
- `warnings`: Reserved for future use as a standard place to put
257
non-fatal warnings in responses. Will be an array but the warning
258
structure/type is not yet specified. Intended primarily as a
259
debugging tool, and will "probably not" become part of the public
260
client interface.
261
- `g`: Fossil administrators (those with the "a" or "s" permissions)
262
may set the `debugFossilG` boolean request parameter (CLI:
263
`--json-debug-g`) to enable this property for any given response. It
264
contains a good deal of the server-side internal state at the time
265
the response was generated, which is often useful in debuggering
266
problems. Trivia: it is called "g" because that's the name of
267
fossil's internal global state object.
268
- `procTimeMs`: For debugging only - generic clients must not rely on
269
this property. Contains the number of milliseconds the JSON command
270
processor needed to dispatch and process the command. TODO: move the
271
timer into the fossil core so that we can generically time its
272
responses and include the startup overhead in the time calculation.
273
274
275
276
<a id="http-response-header"></a>
277
# HTTP Response Headers
278
279
The Content-Type HTTP header of a response will be either
280
application/json, application/javascript, or text/plain, depending on
281
whether or not we are in JSONP mode or (failing that) the contents of
282
the "Accept" header sent in the request. The response type will be
283
text/plain if it cannot figure out what to do. The response's
284
Content-Type header *may* contain additional metadata, e.g. it might
285
look like: application/json; charset=utf-8
286
287
Apropos UTF-8: note that JSON is, by definition, Unicode and recommends
288
UTF-8 encoding (which is what we use). That means if your console cannot
289
handle UTF-8 then using this API in CLI mode might (depending on the
290
content) render garbage on your screen.
291
292
293
<a id="cli-vs-http"></a>
294
# CLI vs. HTTP Mode
295
296
CLI (command-line interface) and HTTP modes (CGI and standalone server)
297
are consolidated in the same implementations and behave essentially
298
identically, with only minor exceptions.
299
300
An HTTP path of `/json/foo` translates to the CLI command `fossil json
301
foo`. CLI mode takes options in the fossil-convention forms (e.g. `--foo 3`
302
or `-f 3`) whereas HTTP mode takes them via GET/POST data (e.g. `?foo=1`).
303
(Note that per long-standing fossil convention CLI parameters taking a
304
value do not use an equal sign before the value!)
305
306
For example:
307
308
- HTTP: `/json/timeline/wiki?after=2011-09-01&limit=3`
309
- CLI: `fossil json timeline wiki --after 2011-09-01 --limit 3`
310
311
Some commands may only work in one mode or the other (for various
312
reasons). In CLI mode the user automatically has full setup/admin
313
access.
314
315
In HTTP mode, request-specific options can also be specified in the
316
`POST.payload` data, and doing so actually has an advantage over
317
specifying them as URL parameters: posting JSON data retains the full
318
type information of the values, whereas GET-style parameters are always
319
strings and must be explicitly type-checked/converted (which may produce
320
unpredictable results when given invalid input). That said, oftentimes
321
it is more convenient to pass the options via URL parameters, rather
322
than generate the request envelope and payload required by POST
323
requests, and the JSON API makes some extra effort to treat GET-style
324
parameters type-equivalent to their POST counterparts. If a property
325
appears in both GET and `POST.payload`, GET-style parameters *typically*
326
take precedence over `POST.payload` by long-standing convention (=="PHP
327
does it this way by default").
328
329
(That is, however, subject to eventual reversal because of the
330
stronger type safety provided by POSTed JSON. Philosophically
331
speaking, though, GET *should* take precedence, in the same way that
332
CLI-provided options conventionally override app-configuration-level
333
options.)
334
335
One notable functional difference between CLI and HTTP modes is that in
336
CLI mode error responses *might* be accompanied by a non-0 exit status
337
(they "should" always be, but there might be cases where that does not
338
yet happen) whereas in HTTP mode we always try to exit with code 0 to
339
avoid generating an HTTP 500 ("internal server error"), which could keep
340
the JSON response from being delivered. The JSON code only intentionally
341
allows an HTTP 500 when there is a serious internal error like
342
allocation or assertion failure. HTTP clients are expected to catch
343
errors by evaluating the response object, not the HTTP result code.
344
345
<a id="simulating-post-data"></a>
346
# Simulating POSTed data
347
348
We have a mechanism to feed request data to CLI mode via
349
files (simulating POSTed data), as demonstrated in this example:
350
351
```console
352
$ cat in.json
353
{ "command": "timeline/wiki", "indent":2, "payload":{"limit":1}}
354
$ fossil json --json-input in.json # use filename - for stdin
355
```
356
357
The above is equivalent to:
358
359
```console
360
$ echo '{"indent":2, "payload":{"limit":1}}' \
361
| fossil json timeline wiki --json-input -
362
```
363
364
Note that the "command" JSON parameter is only checked when no json
365
subcommand is provided on the CLI or via the HTTP request path. Thus we
366
cannot pass the CLI args "json timeline" in conjunction with a "command"
367
string of "wiki" this way.
368
369
***HOWEVER...***
370
371
Much of the existing JSON code was written before the `--json-input`
372
option was possible. Because of this, there might be some
373
"misinteractions" when providing request-specific options via *both*
374
CLI options and simulated POST data. Those cases will eventually be
375
ironed out (with CLI options taking precedence). Until then, when
376
"POSTing" data in CLI mode, for consistent/predictible results always
377
provide any options via the JSON request data, not CLI arguments. That
378
said, there "should not" be any blatant incompatibilities, but some
379
routines will prefer `POST.payload` over CLI/GET arguments, so there
380
are some minor inconsistencies across various commands with regards to
381
which source (POST/GET/CLI) takes precedence for a given option. The
382
precedence "should always be the same," but currently cannot be due to
383
core fossil implementation details (the internal consolidation of
384
GET/CLI/POST vars into a single set).
385
386
387
<a id="json-indentation"></a>
388
# Indentation/Formatting of JSON Output
389
390
CLI mode accepts the `--indent|-I #` option to set the indention level
391
and HTTP mode accepts `indent=#` as a GET/POST parameter. The semantics
392
of the indention level are derived from the underlying JSON library and
393
have the following meanings: 0 (zero) or less disables all superfluous
394
indentation (this is the default in HTTP mode). A value of 1 uses 1 hard
395
TAB character (ASCII 0x09) per level of indention (the default in CLI
396
mode). Values greater than 1 use that many whitespaces (ASCII 32d) per
397
level of indention. e.g. a value of 7 uses 7 spaces per level of
398
indention. There is no way to specify one whitespace per level, but if
399
you *really* want one whitespace instead of one tab (same data size) you
400
can filter the output to globally replace ASCII 9dec (TAB) with ASCII
401
32dec (space). Because JSON string values *never* contain hard tabs
402
(they are represented by `\t`) there is no chance that such a global
403
replacement will corrupt JSON string contents - only the formatting will
404
be affected.
405
406
Potential TODO: because extraneous indention "could potentially" be used
407
as a form of DoS, the option *might* be subject to later removal from HTTP
408
mode (in CLI it's fine).
409
410
In HTTP mode no trailing newline is added to the output, whereas in CLI
411
mode one is normally appended (exception: in JSONP mode no newline is
412
appended, to (rather pedantically and arbitraily) allow the client to
413
add a semicolon at the end if he likes). There is currently no option to
414
control the newline behaviour, but the underlying JSON code supports
415
this option, so adding it to this API is just a matter of adding the
416
CLI/HTTP args for it.
417
418
Pedantic note: internally the indention level is stored as a single
419
byte, so giving large indention values will cause harmless numeric
420
overflow (with only cosmetic effects), meaning, e.g., 257 will overflow
421
to the value 1.
422
423
Potential TODO: consider changing cson's indention mechanism to use a
424
*signed* number, using negative values for tabs and positive for
425
whitespace count (or the other way around). This would require more
426
doc changes than code changes :/.
427
428
429
<a id="jsonp"></a>
430
# JSONP
431
432
The API supports JSONP-style output. The caller specifies the callback
433
name and the JSON response will be wrapped in a function call to that
434
name. For HTTP mode pass the `jsonp=string` option (via GET or POST
435
envelope) and for CLI use `--jsonp string`.
436
437
For example, if we pass the JSONP name `myCallback` then a response will
438
look like:
439
440
```js
441
myCallback({...response...})
442
```
443
444
Note that fossil does not evaluate the callback name itself, other than
445
to verify that it is-a string, so "garbage in, garbage out," and all
446
that. (Remember that CLI and GET parameters are *always* strings, even
447
if they *look* like numbers.)
448
449
450
<a id="result-codes"></a>
451
# API Result Codes
452
453
Result codes are strings which tell the client whether or not a given
454
API call succeeded or failed, and if it failed *perhaps* some hint as to
455
why it failed.
456
457
The result code is available via the resultCode property of every
458
*error* response envelope. Since having a result code value for success
459
responses is somewhat redundant, success responses contain no resultCode
460
property. In practice this simplifies error checking on the client side.
461
462
The codes are strings in the form `FOSSIL-####`, where `####` is a
463
4-digit integral number, left-padded with zeros. The numbers follow
464
these conventions:
465
466
- The number 0000 is reserved for the "not an error" (OK) case. Since
467
success responses do not contain a result code, clients won't see
468
this value (except in documentation).
469
- All numbers with a leading 0 are reserved for *potential* future use
470
in reporting non-fatal warnings.
471
- Despite *possibly* having leading zeros, the numbers are decimal,
472
not octal. Script code which uses eval() or similar to produce
473
integers from them may need to take that into account.
474
- The 1000ths and 100ths places of the number describe the general
475
category of the error, e.g. authentication- vs. database- vs. usage
476
errors. The 100ths place is more specific than the 1000ths place,
477
allowing two levels of sub-categorization (which "should be enough"
478
for this purpose). This separation allows the server administrator
479
to configure the level of granularity of error reporting. e.g. some
480
admins consider error messages to be security-relevant and like to
481
"dumb them down" on their way to the client, whereas developers
482
normally want to see very specific error codes when tracking down a
483
problem. We can offer a configuration option to "dumb down" error
484
codes to their generic category by simply doing a modulo 100
485
(or 1000) against the native error code number. e.g. FOSSIL-1271
486
could (via a simple modulo) be reduced to FOSSIL-1200 or
487
FOSSIL-1000, depending on the paranoia level of the sysadmin. I have
488
tried to order the result code numbers so that a dumb-down level of
489
2 provides reasonably usable results without giving away too much
490
detail to malicious clients.\
491
(**TODO:** `g.json.errorDetailParanoia` is used to set the
492
default dumb-down level, but it is currently set at compile-time.
493
It needs to be moved to a config option. We have a chicken/egg scenario
494
with error reporting and db access there (where the config is
495
stored).)
496
- Once a number is assigned to a given error condition (and actually
497
used somewhere), it may not be changed/redefined. JSON clients need
498
to be able to rely on stable result codes in order to provide
499
adequate error reporting to their clients, and possibly for some
500
error recovery logic as well (i.e. to decide whether to abort or
501
retry).
502
503
The *tentative* list of result codes is shown in the following table.
504
These numbers/ranges are "nearly arbitrarily" chosen except for the
505
"special" value 0000.
506
507
**Maintenance reminder:** these codes are defined in
508
[`src/json_detail.h`](/finfo/src/json_detail.h) (enum
509
`FossilJsonCodes`) and assigned default `resultText` values in
510
[`src/json.c:json_err_cstr()`](/finfo/src/json.c). Changes there need
511
to be reflected here (and vice versa). Also, we have assertions in
512
place to ensure that C-side codes are in the range 1000-9999, so do
513
not just go blindly change the numeric ranges used by the enum.
514
515
516
**`FOSSIL-0###`: Non-error Category**
517
518
- `FOSSIL-0000`: Success/not an error. Succesful responses do not
519
contain a resultCode, so clients should never see this.
520
- `FOSSIL-0###`: Reserved for potential future use in reporting
521
non-fatal warnings.
522
523
524
525
**`FOSSIL-1000`: Generic Errors Category**
526
527
- `FOSSIL-1101`: Invalid request. Request envelope is invalid or
528
missing.
529
- `FOSSIL-1102`: Unknown JSON command.
530
- `FOSSIL-1103`: Unknown/unspecified error
531
- `FOSSIL-1104`: RE-USE
532
- `FOSSIL-1105`: A server-side timeout was reached. (i’m not sure we
533
can actually implement this one, though.)
534
- `FOSSIL-1106`: Assertion failed (or would have had we
535
continued). Note: if an `assert()` fails in CGI/server modes, the HTTP
536
response will be code 500 (Internal Server Error). We want to avoid
537
that and return a JSON response instead. All of that said - there seems
538
to be little reason to implement this, since assertions are "truly
539
serious" errors.
540
- `FOSSIL-1107`: Allocation/out of memory error. This cannot be reasonably
541
reported because fossil aborts if an allocation fails.
542
- `FOSSIL-1108`: Requested API is not yet implemented.
543
- `FOSSIL-1109`: Panic! Fossil's `fossil_panic()` or `cgi_panic()` was
544
called. In non-JSON HTML mode this produces an HTTP 500
545
error. Clients "should" report this as a potential bug, as it
546
"possibly" indicates that the C code has incorrect argument- or
547
error handling somewhere.
548
- `FOSSIL-1110`: Reading of artifact manifest failed. Time to contact
549
your local fossil guru.
550
- `FOSSIL-1111`: Opening of file failed (e.g. POST data provided to
551
CLI mode).
552
553
554
**`FOSSIL-2000`: Authentication/Access Error Category**
555
556
- `FOSSIL-2001`: Privileged request was missing authentication
557
token/cookie.
558
- `FOSSIL-2002`: Access to requested resource was denied. Oftentimes
559
the `resultText` property will contain a human-language description of
560
the access rights needed for the given command.
561
- `FOSSIL-2003`: Requested command is not available in the current
562
operating mode. Returned in CLI mode by commands which require HTTP
563
mode (e.g. login), and vice versa. FIXME: now that we can simulate
564
POST in CLI mode, we can get rid of this distinction for some of the
565
commands.
566
- `FOSSIL-2100`: Login Failed.
567
- `FOSSIL-2101`: Anonymous login attempt is missing the
568
"anonymousSeed" property (fetched via [the `/json/anonymousPassword`
569
request](api-auth.md#login-anonymous)). Note that this is more
570
specific form of `FOSSIL-3002`.
571
572
573
ONLY FOR TESTING purposes should the remaning 210X sub-codes be
574
enabled (they are potentially security-relevant, in that the client
575
knows which part of the request was valid/invalid):
576
577
- `FOSSIL-2102`: Name not supplied in login request
578
- `FOSSIL-2103`: Password not supplied in login request
579
- `FOSSIL-2104`: No name/password match found
580
581
582
**`FOSSIL-3000`: Usage Error Category**
583
584
- `FOSSIL-3001`: Invalid argument/parameter type(s) or value(s) in
585
request
586
- `FOSSIL-3002`: Required argument(s)/parameter(s) missing from
587
request
588
- `FOSSIL-3003`: Requested resource identifier is ambiguous (e.g. a
589
shortened hash that matches multiple artifacts, an abbreviated
590
date that matches multiple commits, etc.)
591
- `FOSSIL-3004`: Unresolved resource identifier. A branch/tag/uuid
592
provided by client code could not be resolved. This is a special
593
case of #3006.
594
- `FOSSIL-3005`: Resource already exists and overwriting/replacing is
595
not allowed. e.g. trying to create a wiki page or user which already
596
exists. FIXME? Consolidate this and resource-not-found into a
597
separate category for dumb-down purposes?
598
- `FOSSIL-3006`: Requested resource not found. e.g artifact ID, branch
599
name, etc.
600
601
602
**`FOSSIL-4000`: Database-related Error Category**
603
604
- `FOSSIL-4001`: Statement preparation failed.
605
- `FOSSIL-4002`: Parameter binding failed.
606
- `FOSSIL-4003`: Statement execution failed.
607
- `FOSSIL-4004`: Database locked (this is not used anywhere, but
608
reserved for future use).
609
610
Special-case DB-related errors...
611
612
- `FOSSIL-4101`: Fossil Schema out of date (repo rebuild required).
613
- `FOSSIL-4102`: Fossil repo db could not be found.
614
- `FOSSIL-4103`: Repository db is not valid (possibly corrupt).
615
- `FOSSIL-4104`: Check-out not found. This is similar to FOSSIL-4102
616
but indicates that a local checkout is required (but was not
617
found). Note that the 4102 gets triggered earlier than this one, and
618
so can appear in cases when a user might otherwise expect a 4104
619
error.
620
621
622
Some of those error codes are of course "too detailed" for the client to
623
do anything with (e.g.. 4001-4004), but their intention is to make it
624
easier for Fossil developers to (A) track down problems and (B) support
625
clients who report problems. If a client reports, "I get a FOSSIL-4000,
626
how can I fix it?" then the developers/support personnel can't say much
627
unless they know if it's a 4001, 4002, 4003, 4004, or 4101 (in which
628
case they can probably zero in on the problem fairly quickly, since they
629
know which API call triggered it and they know (from the error code) the
630
general source of the problem).
631
632
## Why Standard/Immutable Result Codes are Important
633
634
- They are easily internationalized (i.e. associated with non-English
635
error text)
636
- Clients may be able to add automatic retry strategies for certain
637
problem types by examining the result code. e.g. if fossil returns a
638
locking or timeout error \[it currently does no special
639
timeout/locking handling, by the way\] the client could re-try,
640
whereas a usage error cannot be sensibly retried with the same
641
inputs.
642
- The "category" structure described above allows us some degree of
643
flexibility in how detailed the reported errors are reported.
644
- While the string prefix "FOSSIL-" on the error codes may seem
645
superfluous, it has one minor *potential* advantage on the client
646
side: when managing several unrelated data sources, these error
647
codes can be immediately identified (by higher-level code which may
648
be ignorant of the data source) as having come from the fossil API.
649
Think "ORA-111" vs. "111".
650

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button