Errors, exceptions, and null handling

~11 min

Imagine ordering coffee through an app. Somewhere in the system, code checks your order and attempts to process your payment.

But what happens if your saved card has expired? What if your cart is empty? What if the application expects a delivery address, but none has been provided?

So far, you have mostly read code in situations where everything goes as expected, but real software must also respond to invalid inputs, missing information, unavailable services, and other unexpected situations.

Understanding how software handles these unhappy paths is part of technical literacy.

What is an error?

An Concept · lights on your maperrorA general term for a problem that prevents software from behaving as intended, from invalid syntax to a missing file to an unavailable service. “It returned an error” means the operation did not complete successfully. is a general term for a problem that prevents software from behaving as intended.

Errors can occur for many reasons. The source code may contain invalid syntax, the program may receive information in an unexpected format, a file may be missing, or a remote service may be unavailable.

Examples include:

  • A missing quotation mark that prevents the code from running
  • A program attempting to divide a number by zero
  • A payment system being temporarily unavailable
  • Code attempting to use information that does not exist
  • A calculation producing the wrong result

Engineers often use the word error broadly. Saying that a request “returned an error” usually means that the operation did not complete successfully, although more investigation may be needed to understand why.

An error is not always the same as a bug, which is a flaw in the software that causes incorrect behavior. An error may be caused by a bug, but it can also result from something outside the program, such as a lost network connection.

Expected failures are not always exceptions

Some unsuccessful outcomes are normal and should be anticipated by the product.

A declined card, for example, may not indicate that the payment system malfunctioned. The system may have worked correctly and returned a valid result saying that the bank rejected the payment.

Similarly, an empty shopping cart may be a normal state that the application should recognize and explain to the user.

Professional software tries to distinguish between:

  • An expected negative outcome, such as a declined payment
  • Invalid input, such as an incorrectly formatted card number
  • An unexpected technical failure, such as the payment service becoming unreachable

These situations may all prevent the user from completing a purchase, but the software may handle them differently.

What is an exception?

An Concept · lights on your mapexceptionAn event that interrupts the normal flow of a program because something unusual or problematic occurred. Code “throws” (or “raises”) an exception; other code can “catch” it and respond, or the affected operation stops. is an event that interrupts the normal flow of a program because something unusual or problematic occurred.

Imagine that a program attempts to open a file that does not exist. The programming language may create, or raise, an exception to indicate that the operation could not continue normally.

Engineers also commonly say that the code throws an exception.

Other code can sometimes catch the exception and decide what to do next. It might display a helpful message, record the problem in a log, try the operation again, or choose an alternative path.

For example:

Catching an exceptionPython
1try:
2receipt = open_receipt_file()
An operation that might fail.
3except FileNotFoundError:
If this particular problem occurs…
4show_message("The receipt could not be found.")
…respond helpfully instead of stopping.

The try section contains an operation that might fail, and the except section describes how the program should respond to a particular exception.

You do not need to memorize this syntax. The pattern is: code attempts an operation. If a known problem occurs, other code catches it and responds.

If an exception is not handled, the current operation may stop. In a small program, that may end the entire program, while in a larger application, it may stop only one request, process, or part of the system.

What is null?

Sometimes a program expects a value, but no value is available.

Many programming languages represent this absence using a special value called Concept · lights on your mapnull handlingNull (None in Python, nil in some other languages) is the special value meaning that no value exists, different from empty text or an empty list. Null handling is the discipline of checking for the absence of a value before attempting to use it.. Different languages use names such as:

  • null
  • None
  • nil

Python uses None.

Suppose a customer has not saved a delivery address: saved_address = None

This does not mean that the address is a blank piece of text. It means that no address value exists.

This distinction matters because the following values mean different things:

  • None means there is no value.
  • "" is an empty string: text exists, but it contains no characters.
  • [] is an empty list: the list exists, but it currently contains no items.

A program may need to respond differently to each situation.

Why null can cause problems

Imagine that an address normally contains a ZIP code: zip_code = saved_address.zip_code

If saved_address contains a real address, the code may work, but if it contains None, there is no address from which to retrieve a ZIP code.

The program is effectively being asked: what is the ZIP code of something that does not exist?

That can cause an exception.

To prevent this, the code can check for the missing value before attempting to use it:

Null handling: the check before the usePython
1address = customer.saved_address
Might be a real address object. Might be None, Python's word for null.
2
3if address is None:
The null check: before touching it, ask “is there nothing here?”
4show_message("Please add a delivery address.")
Graceful path: a helpful prompt instead of a crash.
5else:
6deliver_to(address.zip_code)
Only now is it safe to use the ZIP code.

The conditional first asks whether the address is missing.

If it is, the program displays a helpful message. If an address exists, the program can safely use its ZIP code.

This is an example of null handling: deliberately checking for the absence of a value and deciding what should happen. Check first, then use.

Graceful error handling

Good software does more than avoid crashing. It attempts to handle problems in a way that helps the user and protects the system.

This is sometimes described as failing gracefully.

If a payment is declined, the application should explain what happened and allow the user to choose another payment method.

If the network temporarily disappears, the application might preserve the user’s work and try again after the connection returns.

If required information is missing, the application should ask the user to provide it rather than displaying a confusing technical message.

Graceful handling may involve:

  • Showing a clear message
  • Preserving the user’s work
  • Retrying an operation
  • Using a fallback option
  • Recording the error for engineers
  • Preventing incomplete or invalid data from being saved

The right response depends on the type of problem.

Why the unhappy paths require work

A feature can appear simple when described only through its ideal path.

For example: allow a customer to place an order.

But a complete implementation must consider many additional situations:

  • What if the cart is empty?
  • What if an item sells out?
  • What if the card is declined?
  • What if the network disconnects?
  • What if the customer submits the order twice?
  • What if required information is missing?
  • What if the payment succeeds but the confirmation fails?

Engineers call these situations failure cases, or unhappy paths. Some of them are also edge cases, a word Module 11 comes back to properly.

Handling them is more than optional polish. It is part of making a feature dependable enough for real users.

This is one reason engineering estimates may be larger than the visible feature first suggests. Building the main path is only part of the work because the team must also decide how the system should behave when reality does not follow the ideal path. Reality rarely cooperates.

Tools that catch problems early

Engineers use several tools to identify potential problems before software reaches users.

Recognition — just know it existslintingAn automated checker that examines source code for suspicious patterns, style problems, and certain common mistakes, like spell-check for code. Runs constantly in engineers’ editors. examines source code for suspicious patterns, style problems, and certain common mistakes.

Recognition — just know it existsstatic analysisThe broader family of tools that inspect code without executing it, attempting to identify possible defects, security issues, or unsafe behavior. inspects code without executing it and attempts to identify possible defects, security issues, or unsafe behavior.

Recognition — just know it existstype checkingVerifying automatically that values are used in ways that match their expected data types (for example, warning when code attempts to treat text as a number). The “1250” string-gluing bug from the data-types lesson is exactly what it prevents. verifies that values are being used in ways that match their expected data types. For example, it may warn that code is attempting to treat text as a number.

These categories can overlap, and the exact capabilities depend on the language and tool, so at this stage, recognize them as automated safety checks that can catch some problems before the software runs in production.

They cannot prove that the code is completely correct, so engineers still need testing, monitoring, and careful reasoning.

The mental model to remember

An error is a general problem that prevents software from behaving as intended.

A bug is a flaw in the software that causes incorrect behavior.

An exception interrupts the normal flow of a program. Code may catch it and respond, or the affected operation may stop.

Null represents the absence of a value. It is different from empty text, an empty list, or the number zero.

Null handling means checking whether a value exists before attempting to use it.

An unhappy path is a situation in which something does not go according to the feature’s ideal flow.

You should now understand that reliable software must account not only for what should happen, but also for what might go wrong.

Check — then the lesson continues

An engineer in standup says: “Checkout crashes for some users — turns out we never handled the case where the cart is empty.” Translate to this lesson's vocabulary.

▼ answer the check to continue ▼