Error handling

Handle error responses of the Redmine API.

When Redmine answers with a status code that isn't a success response of the operation, the method throws a RestError with:

PropertyDescription
statusThe HTTP status code
bodyThe response body, e.g. the validation errors
headersThe response headers
requestThe request, with its method and url
messagee.g. Unexpected HTTP status code: 404 - HTTP 404 received for GET …

Network errors (server not reachable, invalid certificate) are thrown as they are, without a status.

Status codes

StatusMeaning in Redmine
401Missing or invalid API key, or the REST API is disabled
403The user isn't allowed to do this, e.g. an admin-only endpoint
404The resource doesn't exist, or the user can't see it (e.g. an issue of a private project)
422Validation failed, the messages are in body.errors

Checking the status

RestError isn't exported, so check for the status property:

errors.ts
interface RedmineError extends Error {
  status: string | number;
  body?: { errors?: string[] };
}

export const isRedmineError = (error: unknown, status?: number): error is RedmineError =>
  error instanceof Error && "status" in error && (status === undefined || Number(error.status) === status);
try {
  await client.issuesClient.createIssue({ issue: { projectId: 1, subject: "" } });
} catch (error) {
  if (isRedmineError(error, 422)) {
    console.error(error.body?.errors); // ["Subject cannot be blank"]
  } else {
    throw error;
  }
}

Not found

To treat a missing resource as undefined instead of an error:

const findIssue = async (id: number) => {
  try {
    return (await client.issuesClient.getIssue(id)).issue;
  } catch (error) {
    if (isRedmineError(error, 404)) return undefined;
    throw error;
  }
};

On this page