Skip to content

API errors and paging through results

How to shape an error so a program can read it, why a long list is returned in pages, offset against cursor paging, and how an OpenAPI file documents the API.

  • Lesson 10 of 125
  • 12 min read
  • Core
  • Free to read, no account
On this page
  1. Why interviewers ask this
  2. The idea in plain words
  3. Pause and predict
  4. Worked example
  5. Trade-offs
  6. Common misconceptions
  7. How to say it in the interview
  8. Check your understanding
  9. Answers
  10. Sources

What you need first

This lesson uses ideas from these earlier lessons. Read them first if any idea is new to you.

01Why interviewers ask this

In the API step (lesson 2), interviewers ask: "What does the client get back when something fails?" And: "A shop has 10 lakh (1,000,000) orders. How does the app get page 2?"

A weak answer returns every order in one call, with errors as free text. A strong answer returns small pages, and errors in one fixed shape that a program can read. In our own guide, SDE-1 can use offset paging. SDE-2 and above should say why a cursor is better.

02The idea in plain words

Think about a library desk. A good librarian says why a book is missing. For a long shelf, the librarian hands you 20 books and a bookmark.

Error shape. The status code (lesson 9) gives the family. The body gives the detail. Use the same body for every error, so the client needs one piece of code to read it. A public standard is RFC 9457, "problem details", sent as application/problem+json. It has these members:

  • type: the kind of problem, written as a URL. It never changes for that kind of problem.
  • title: a short summary for people.
  • status: the status code again.
  • detail: the explanation for this one case.
  • instance: a name for this one occurrence.

You may add members, such as request_id, which helps support find the call. Programs should check type, not title.

Paging. A page is a small part of a long list. Paging means one page per call, which protects the server and the phone. Cap the page size with a limit, for example 100. Both styles below put inputs after the ? in the URL. These are query parameters.

  • Offset paging: GET /orders?limit=20&offset=40 means "skip 40 rows, then return 20". It is simple, and the client can jump to any page. It has two problems. The database must still work through the skipped rows. And if rows are added or removed between two calls, the pages shift: you see an item twice, or you miss one.
  • Cursor paging: GET /orders?limit=20&cursor=abc. A cursor is a token that marks the last item the client saw. The server returns the 20 items after it, and a next_cursor. At the end of the list it is null. Inside the token is usually the last row's id, so the database can jump straight to it. This works because the ids are kept in sorted order. Sort by a unique value, such as id, or items with equal values can switch places between calls. The client must not read the token. Cursor paging costs you the jump to page 50, and a total count is extra work.

OpenAPI. An OpenAPI file is a text file (YAML or JSON) that describes your API: paths, methods, inputs, answers and error bodies. Tools turn it into a documentation page, make client code and check the server. You write it in the API step, before the code. Part of a file:

yaml
paths:
  /orders:
    get:
      parameters:
        - {name: limit, in: query, schema: {type: integer, maximum: 100}}
        - {name: cursor, in: query, schema: {type: string}}
      responses:
        "200": {description: One page of orders}
        "400": {description: Bad input (problem details)}

Stuck on something? The AI tutor has read this lesson. Ask it with a free account

03Pause and predict

Pause. Guess first.

A list shows newest orders first. A user reads page 1, items 1 to 20. Then 5 new orders arrive. The app asks for offset=20. Which old items does it get twice?

Write your guess before you read on. The answer is in the worked example.

04Worked example

Assumption: the shop has 1,000,000 orders. The page size is 20.

Work for the last page. Offset paging asks for offset=999980. The database works through 999,980 + 20 = 1,000,000 rows. Cursor paging works through 20 rows. That is 1,000,000 / 20 = 50,000 times more rows. This counts rows, not time.

Pages that shift. Page 1 held items 1 to 20. Every old item has moved down 5 places, so old items 16 to 20 are at positions 21 to 25. The call offset=20 returns positions 21 to 40, which are old items 16 to 35. So old items 16 to 20 appear twice: 5 repeats. This answers the predict box. A cursor "after old item 20" returns old items 21 to 40: no repeat.

An error. The app sends limit=500, but the maximum is 100. The server returns 400 and this body:

json
{
  "type": "https://api.example.com/errors/limit-too-large",
  "title": "limit is too large",
  "status": 400,
  "detail": "limit must be 100 or less. You sent 500.",
  "request_id": "r-81f2"
}

05Trade-offs

  • Cursor paging solves repeated or missing items and slow deep pages. It costs page jumps and an easy total. I would use offset for a small, fixed list.
  • One error shape solves guessing. It costs agreement across all teams. I would add fields only when needed.

06Common misconceptions

"Offset paging is fine, because databases are fast." The database still works through every skipped row, and shifting rows cause repeats.

"A cursor is just the last id, so the client may build it." The server may change what is inside the token. A client that builds its own cursor then breaks.

"The message text is enough for the client." Text changes and may be translated. A program reads type.

07How to say it in the interview

Say it like this

I would page the order list with a cursor and a limit of 100, so deep pages stay fast and no item repeats. Errors use one problem-details body with a fixed type, and I would write the API in an OpenAPI file.

08Check your understanding

  1. Name the two paging styles. Give one problem of each.
  2. A table has 200,000 rows and the page size is 50. For the last page, how many rows does each style work through? How many times more?
  3. Your app shows the same order at the end of one page and the start of the next. Why does it happen, and what do you change?

09Answers

Show the answers
  1. Offset: the database works through skipped rows, and pages shift. Cursor: no jump to a page number, and no easy total.
  2. Offset: 199,950 + 50 = 200,000 rows. Cursor: 50 rows. 200,000 / 50 = 4,000 times more.
  3. New rows pushed items down between the calls, and offset counts from the top. Use cursor paging with a unique sort order.

10Sources

Try it now, no sign-up

More practice, in the app (free account)

Ask the AI tutor about this lesson

The tutor has read this lesson. Ask in your own words, any time. Free account, 20 questions a day.

Reading never needs an account. The account is for the tutor, the quiz, your notes and your progress.

All lessons in Module 2: Web and API basics