Common Error Codes and Causes

The following is a non-exhaustive list of various error codes that you may encounter and provides some possible causes for them.

401 Unauthorized

Indicates that the Resource to access is only accessible to certain agents, but the current user is not logged in.

If the user is logged in but still receives this error, you might not have passed the session’s fetch() function as an option to the function sending the request.

403 Forbidden

Indicates that the current user is logged in but does not have the required level of access to the resource.

404 Not Found

Indicates that the Resource the user is trying to fetch does not exist.

409 Conflict

Indicates that the data you are trying to modify has been changed since your fetch operation, e.g., by a different person or on a different device.

Specifically, a SolidDataset keeps a changelog that tracks both the old value and new values of the property being modified. Then, the save operation applies the changes from the changelog to the current SolidDataset. If the old value specified in the changelog does not correspond to the value currently in the Pod, the save operation returns a 409 Conflict error. For more information, see Changelog Considerations.

Inrupt’s Enterprise Solid Server will also return 409 Conflict error when it encounters unexpected data, like setting a Thing’s rdf::type to an integer rather than a URL.

412 Precondition Failed

Indicates that a condition that is set by solid-client before proceeding with the request is not met.

For example, saveSolidDatasetAt attempts to create a new Resource at the specified URL if the passed-in Resource has no URL identifying it. When creating a new Resource, the function adds the precondition that the Resource must not already exist. If the Resource already exists, 412 Precondition Failed error is returned.

Consider the following code sequence which results in the 412 error:

let myReadingList = createSolidDataset();

// ... Modify the myReadingList as needed.

// Perform Save: Create the Resource at specified location
let savedReadingList = await saveSolidDatasetAt(
  READING_LIST_URL,       // Location to save the new Resource
  myReadingList,          // No identifying URL associated with the `myReadingList`
  { fetch: fetch }

// ... Modify the myReadingList as needed.

// Perform Save: Attempts to create the Resource instead of overwrite.
savedReadingList = await saveSolidDatasetAt(
  myReadingList,          // Still no identifying URL associated with `myReadingList`
  { fetch: fetch }

The code sequence:

  1. Creates a local instance of a SolidDataset (i.e., has no identifying URL information).

  2. Calls saveSolidDatasetAt to save the SolidDataset in a Pod. Since there is no identifying URL associated with the myReadingList, the operation performs a create operation:

    • The returned savedReadingList is the saved version of the SolidDataset you sent and has its identifying URL information, whereas

    • The local myReadingList is unaffected by the save operation and still has no identifying URL information.

  3. Calls saveSolidDatasetAt again with myReadingList. Since there is no identifying URL associated with the myReadingList, the operation attempts to perform a create operation. However, since the previous saveSolidDatasetAt has created the Resource in the Pod, the second saveSolidDatasetAt with myReadingList fails with a 412 error.

To avoid the 412 error on the second save, you can use the SolidDataset returned by the function, in this example savedReadingList which reflects your changes, or explicitly fetch the SolidDataset (e.g., using getSolidDataset) which reflects the most recent changes at the time of the fetch.

By using either the returned SolidDataset or the fetched SolidDataset, saveSolidDatasetAt attempts to update, rather than create, the SolidDataset.


  • When performing an update of an existing SolidDataset, you may encounter 409 Conflict error if another operation has made conflicting modifications to the Resource you are trying to save.

  • saveSolidDatasetAt returns a SolidDataset that reflects only the sent data. That means, if another process made separate non-conflicting modifications to the SolidDataset before you save, the returned SolidDataset only reflects your changes. To make sure you have the latest data, fetch the SolidDataset again with getSolidDataset.