Error handling

One simple rule:

  • If all goes well, most API methods respond with a HTTP 200 status.
  • If somethings goes wrong, you will get a HTTP 4xx response. These kind of responses will usually trigger some kind of an exception inside your application. In some cases you will be able to provide your user with a proper message - see the user_messages key below.

You must catch such exceptions and deal with them properly.

Error Responses

The body of HTTP 4xx response contains JSON-encoded dictionary with the details about the error. Each dictionary has at least the message key, which holds the error description intended for the developer to read.

"error" and "reason" fields

In most cases Error Responses will also contain the error key with the generic code of the thrown error. The list of possible error values is described below. Note that we may introduce new codes in the future.

For some error codes we may provide an additional reason key. Note that one reason can be used with different error codes. Most reason values will be described in the documentation of specific methods, although some common cases are listed below.

Possible error values:

  • method_forbidden - access to the method is denied; in this case reason key is always present;

  • param_missing - required parameter is not provided; an additional key param_name will contain the name of the parameter that caused this error;

  • param_invalid - value of the parameter is invalid; this type of error also contains param_name key;

  • param_forbidden - you are not allowed to use the parameter; in such case param_name and reason will be present;

  • field_not_found - field specified in fields parameter does not exist; the name of the field will be passed in field_name key together with the name of the method (method_name key);

  • field_invalid - specified field is invalid:

    • you have provided subfields for field that does not refer to subobject(s);
    • you have omitted subfields that were required;
    • you have used secondary field, but only primary were allowed.

    field_name and method_name keys will contain the name of the field and its method that caused the error.

  • field_forbidden - you do not have access to some of the requested fields (field_name, method_name and reason keys will be present);

  • object_not_found - some of the referenced objects do not exist; if the object was referenced by one of parameters, the param_name and method_name keys will be present;

  • object_invalid - the referenced object is in state that prevents method execution; the detailed description of such errors is available in method documentation.

  • object_forbidden - access to the referenced object was denied.

Only param_forbidden and object_* errors are explicitly documented in each method. However, other error values may still be present in the documentation if the method provides some additional keys.

Possible reason codes for *_forbidden errors:

  • consumer_missing - consumer signature is missing;
  • user_missing - access token is required;
  • secure_required - secure connection (SSL) is required;
  • trusted_required - only administrative consumers are allowed;
  • scope_missing - access token does not contain some of the required scopes; in this case an additional key missing_scopes will be present in the dictionary with the list of missing scopes;
  • impersonate_required - as_user_id parameter was used with a method which you do not have administrative access to;
  • plus, methods may define their own custom reason codes.

"user_messages" field

Some methods are designed to process data from the user-supplied forms. If such form cannot be submitted for any reason (e.g. the data fails validation), then - as you may expect - the method will return a HTTP 400 response.

Now, you may wonder: As a front-end developer, should you validate the data before you submit it to the API?

The answer is NO. Usually, there's no reason for you to validate the data, which needs to be validated on the server anyway. Most well-designed API methods will perform the validation and return its results to you, so you can display the validation errors to the user.

This is done with the user_messages field. If you ever find this field in the HTTP 400 response, then you should probably parse it's contents, and display them to the user.

user_messages is a dictionary, and currently it may contain two keys (usually only one of them, not both):

  • generic_message - contains a LangDict object, with the generic (context-free) message to be displayed for the user.
  • fields - contains a - possibly empty - dictionary of parameters which have failed the validation, along with LangDict messages for each of them. Usually, the keys of this dictionary will match the named of the method parameters, but it is not a strict rule (e.g. some methods expect the forms to be submitted in a single parameter, as a JSON-encoded string).

Examples:

{
    "message": "Access denied - spam prevention lock.",
    "user_messages": {
        "generic_message": {
            "en": "You have sent over a 100 messages in the last hour. " +
                  "You must wait before you can send another one."
            "pl": "W przeciągu ostatniej godziny wysłałeś ponad 100 " +
                  "wiadomości. Musisz poczekać, zanim pozwolimy Ci wysłać " +
                  "kolejną."
        },
    },
}
{
    "message": "Required parameter fac_id is missing.",
    "error": "param_missing"
    "param_name": "fac_id",
    "user_messages": {
        "fields": {
            "fac_id": {
                "en": "This field is required.",
                "pl": "To pole jest wymagane."
            }
        }
    },
}
{
    "message": "Multiple errors in the user-supplied form.",
    "user_messages": {
        "fields": {
            "fac_id": {
                "en": "This field is required.",
                "pl": "To pole jest wymagane."
            },
            "course_id": {
                "en": "Course no longer conducted. Select another.",
                "pl": "Ten przedmiot nie jest już prowadzony. Wybierz inny."
            }
        }
    },
}

HTTP 401 Unauthorized

Once your application is deployed, this is surely the most frequent kind of error you will get. It occurs whenever the Access Token expires. (It may occur in some other situations, but this is the one situation which you should actually expect.)

When does it happen:

  • When Access Token expires (approx. 2 hours after it was generated).
  • When a user logs out (all of his Access Tokens are destroyed at this moment).
  • When a user revokes access to his account from your application (all of his Access Tokens are destroyed at this moment).

This is very similar to a cookie/session expiration, which is a common issue for web applications and should be dealt with in a similar way.

Usually it looks like this:

  • User sends a HTTP request to your application.
  • While processing user's request, you receive a HTTP 401 ("invalid token") error from USOS API.
  • You make one more USOS API requests to get a new Request Token. (At this point, you may choose to include some additional data in the callback URL.)
  • You must somehow redirect user's browser to the proper authorization page. Usually, you can do that by just responding with a standard HTTP redirect. Sometimes (i.e. if your app uses some fancy AJAX stuff) it will require you to apply some other measures.
  • User visits the authorization page. If the user hadn't logged out (nor removed your application), then USOS API will simply recognize, that the user is still logged in and redirect him to the callback URL you specified. If user logged out [or removed your application], then he will have to log in again first [and authorize your application]. Note, that he may log in as a different user (see below).
  • User returns and visits the callback URL (with the request token and verifier).
  • You exchange the Request Token for an Access Token, and then - just pick up where you left off before.

Note, that from the user's perspective nothing happened - he sent a request to your application, received two or three redirects (which he did not see), and got the page he initially wanted.

Important: You must be prepared for a situation, that the new Access Token you receive above might by actually authorized by other user than you expect. It's not so hard to imagine this scenario: User logs out of USOS account, but does not close his browser - Access Tokens expire in such case, but your session data (based on a HTTP cookie) might be left intact!

HTTP 400 Bad Request

These types of errors are usually caused by an error on your part. You will probably get them frequently during development, but should get rid of most of them before your app is deployed.

The most common causes for HTTP 400 error include:

  • Your request was missing some required parameter.
  • Some of the parameters were invalid (wrong combination or format).
  • You referred to a nonexistent object. For example you tried to get information on a user who didn't exist.
  • You tried to access data with a valid Access Token which did not grant you access to this data. For example you tried to access user's email address without first asking him to do so (via a proper scope).

Unless you're really sure your application is bug-free, you should catch such errors in production environment and mail them to yourself, for future debugging.

HTTP 500 Internal Server Error

These types of errors are caused by an error on USOS API part. They should never happen. In case of its appearance, we will respond to it immediately.

JSON-encoded dictionary with details about this error will be returned in one particular situation. If user with ID extracted from Access Token does not exist, an error with key object_not_found, key message and HTTP 500 status will be thrown.

Invalid consumer / signature

One more type of error is worth mentioning: If you use a invalid Consumer Key or sign your request with invalid signature, you will receive a HTTP 401 Unauthorized error.

Once you have OAuth worked out though, you shouldn't see this error anymore.

USOS API ver. 6.6.0.0-11, 83b82554, dirty (2020-12-21)