Skip to main content

Handling Errors

Applications that implement loading and saving of data typically wish to provide solid error handling. A number of error conditions can occur that are outside the applications control (missing files, unreadable files, incorrectly formatted files etc).Being able to catch these errors and surface meaningful error messages to the end user is important.

Ideally the applications wants a simple and clean API for performing loading, and still have the confidence that errors are caught and meaningful messages are presented to the user.

Types of Errors

There are three main types of errors that arise when attempting to load a data resource:

  1. There is some kind of network/resource access error, preventing the request for data from being completed.
  2. A request is sent to a server, but the server is unable to service the request due to some error condition (often illegal access tokens or request parameters) and sends an error response.
  3. The server returns data, but the parser is unable to parse it (perhaps due to the data being malformatted, or formatted according to an unsupported version of that format).

loaders.gl can detect all of these error conditions and report the resulting errors in a unified way (the errors will be available as exceptions or rejected promises depending on your async programming style, see below).

Error Messages

loaders.gl aims to produce concise, easy-to-understand error messages that can be presented directly to the end user.

  • When the fetch call fails, any exceptions are passed to the user,
  • When a loader fails, it generates an error message.
  • For server error responses, some basic information about the error is compiled into an error message (using e.g. response.status, response.url and occasionally response.text).

Note that while servers often send some information about errors in response.text() when setting HTTP error codes, there are no universally accepted conventions for how servers format those error messages. Server error messages can be JSON or XML encoded for machine consumption, or generated in HTML or clear text format intended to be displayed directly to end user. Even when JSON or XML coded,

loaders.gl makes a "best effort" attempt to extract some meaningful error message from server responses. If you know how your specific service formats errors and want to extract these in a way that you can present to the user, you may want to take control of the fetch calls and Response status checking, see below.

parse Error Handling

parse accepts fetch Response objects, and parse will check the status of the Response before attempting to parse, and generate an exception if appropriate.

Handling Errors from Async Functions

Note that parse is an async function, and in JavaScript, errors generated by async functions will be reported either as an exception or as a rejected promise, depending on how the async funtion was called (using promises or the await keyword):

When using await, errors are reported as exceptions

try {
const response = await fetch(url);
const data = await parse(response);
} catch (error) {
console.log(error);
}

A rejected promise is generated when using Promise.then.

fetch(url)
.then((response) => parse(response))
.catch((error) => console.log(error));

Also note that the Javascript runtime seamlessly converts errors between exceptions and promises in mixed code.

fetch Error Handling

loaders.gl is designed around the use of the modern JavaScript fetch API, so for additional context, it may help to review of how the JavaSctipt fetch function handles errors.

fetch separates between "network errors" that can be detected directly (these cause the fetch to throw an exception) and server side errors that are reported asynchronously with HTTP status codes (in this case the Response object offers accessors that must be called to check if the operation was successful before accessing data).

Example: "manually" checking separately for fetch network errors and server errors:

// Check for network error
let response;
try {
response = await fetch(url);
} catch (error) {
console.log('Network error');
}

// Check for server error
if (!response.ok) {
console.log(`fetch failed with status ${response.status}`);
}

Note that servers often sends a message providing some detail about what went wrong, and that message can be accessed using the standard (asynchronous) response.text() or response.json() methods.

if (!response.ok) {
const errorMessage = await response.text();
// Custom parsing can be done here, if you know how your particular service formats errors
console.log(`fetch failed with status ${errorMessage}`);
}