VOOZH about

URL: https://thenewstack.io/error-handling-from-backends-to-the-frontend/

⇱ Error Handling from Backends to the Frontend - The New Stack


TNS
SUBSCRIBE
Join our community of software engineering leaders and aspirational developers. Always stay in-the-know by getting the most important news and exclusive content delivered fresh to your inbox to learn more about at-scale software development.
REQUIRED
It seems that you've previously unsubscribed from our newsletter in the past. Click the button below to open the re-subscribe form in a new tab. When you're done, simply close that tab and continue with this form to complete your subscription.
The New Stack does not sell your information or share it with unaffiliated third parties. By continuing, you agree to our Terms of Use and Privacy Policy.
Welcome and thank you for joining The New Stack community!
Please answer a few simple questions to help us deliver the news and resources you are interested in.
REQUIRED
REQUIRED
REQUIRED
REQUIRED
REQUIRED
Great to meet you!
Tell us a bit about your job so we can cover the topics you find most relevant.
REQUIRED
REQUIRED
REQUIRED
REQUIRED
REQUIRED
Welcome!

We’re so glad you’re here. You can expect all the best TNS content to arrive Monday through Friday to keep you on top of the news and at the top of your game.

What’s next?

Check your inbox for a confirmation email where you can adjust your preferences and even join additional groups.

Follow TNS on your favorite social media networks.

Become a TNS follower on LinkedIn.

Check out the latest featured and trending stories while you wait for your first TNS newsletter.

PREV
1 of 2
NEXT
VOXPOP
As a JavaScript developer, what non-React tools do you use most often?
Angular
0%
Astro
0%
Svelte
0%
Vue.js
0%
Other
0%
I only use React
0%
I don't use JavaScript
0%
Thanks for your opinion! Subscribe below to get the final results, published exclusively in our TNS Update newsletter:
NEW! Try Stackie AI
From clobbered drafts to real-time sync
Apr 14th 2026 10:00am, by David Moore
TypeScript 6.0 RC arrives as a bridge to a faster future
Mar 14th 2026 9:00am, by Darryl K. Taft
Mastra empowers web devs to build AI agents in TypeScript
Jan 28th 2026 11:00am, by Loraine Lawson
2021-11-01 09:00:57
Error Handling from Backends to the Frontend
contributed,sponsor-logdna,sponsored,sponsored-post-contributed,
DevOps / Software Development

Error Handling from Backends to the Frontend

Errors always happen, perfect test coverage or not. The question is what will you do to handle them with excellence?
Nov 1st, 2021 9:00am by Jonathan Kelley
👁 Featued image for: Error Handling from Backends to the Frontend
Photo by Yan Krukov from Pexels.
LogDNA sponsored this post.
In the 1990s, my Mac OS 7.5.1 would generate an error like this: 👁 Mac OS 7.5.1 error
Why did I have to reboot? And so often! The errors were ambiguous and modern exception handling didn’t exist yet. In Windows 98, you’d get the same ambiguous “blue screen of death.” The reason was because Windows/Macintosh used a shared memory model before protected memory existed, so it was easy for an application to overwrite system memory and crash the kernel. Operating systems have evolved since then, and we’re all happier for it. 👁 Windows blue screen
Errors were quite frequent and annoying in the ’90s, always requiring a reboot. When a memory error happened, you’d get ID = -1 or a hex memory address in Windows corresponding to the cause. These were called error codes, but they weren’t exceptionally helpful or user friendly unless you were an expert developer.

The Old Way of Handling Errors

Jonathan Kelley
Jonathan has been a technologist for 14 years, with a focus on DevOps for half of that. He’s currently a site reliability engineer at LogDNA, where he contributes his expertise about Linux, Kubernetes, networking and cloud infrastructure.
Imagine if you had a C function that took as arguments an array/list of integers and a single integer, and then performed a search. It should return the index of the first match in the index. But what if it didn’t? You’d return -1 or something. That makes error handling simple, right? The problem with this approach is that every caller has to check the return function and handle the error on its own. Lots of checks and “if else” statements in your code will make tons of boilerplate that distract you from the actual business logic. The code was terrible to read and maintain. All too often a return ID was -1, which meant “something broke, but I don’t know what.” What do you do then?

Modern Exceptions (Try) to Save the Day

Exceptions exist to solve all the problems mentioned above. An exception can interrupt software control flow and bubble up to the user with informative data. This is great, but to most users it won’t mean much of anything. When designing your application, always try to catch exceptions you think you’d encounter and then have a generic catchall for cases where unknown problems can be caught. Perform a logging action that’s user-informative or has some other value, so the end user can troubleshoot the cause. To catch an exception in Python using the HTTP requests library, you could do something like:
import requests
url = 'http://www.google.com/bogus'
try:
	r = requests.get(url,timeout=3)
	r.raise_for_status()
except requests.exceptions.HTTPError as e:
	print (f'Http Error: {e}')
 exit(1)
except requests.exceptions.ConnectionError as e:
	print (f'Connect Error: {e}')
 exit(1)
except requests.exceptions.Timeout as e:
	print(f'Timeout Error: {e}')
 exit(1)
except requests.exceptions.RequestException as e:
	print(f'Unknown Error: {e}')
 exit(1)
except Exception as e:
	print(f'Unknown Exception: {e}')
 exit(1)

This is what you’d see when you visit a non-existent URL at Google: Http Error: 404 Client Error: Not Found for url:http://www.google.com/bogus See? Makes a lot more sense than Python’s uncaught exception handler (below):
Traceback (most recent call last):
 File "/tmp/fail.py", line 4, in <module>
	r.raise_for_status()
 File "/usr/local/lib/python3.9/site-packages/requests/models.py", line 943, in raise_for_status
	raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: http://www.google.com/bogus
You want to handle all exceptions, even if it’s just to display a friendly error message and exit the program anyway. Good exception handling should also be used to free up resources, file resources, locks or other things that could break future execution. A super-simple example (don’t do this in practice in Python, you should use Context Manager instead) is to perform something like:
myfile = open('test.txt', 'w')

try:
 myfile.write('the answer to life is: ')
 myfile.write(42) # raises TypeError
except IOError as e:
 print(f'Could not write to file: {e}')
finally:
 myfile.close() # will be executed before TypeError is propagated

Always Use the Most Specific Exception

The more explicit the exception, the better you’re handling errors in code. If your code is using generic try / except blocks everywhere without a specific exception to trap, you have no control over how a specific exception is handled. This also makes exceptions unknown to the caller, which is terrible if a user or developer doesn’t understand the failure modes for your library. You should also investigate the libraries you’re using and understand the exceptions they might throw, so you can take action. Likewise, if you’re developing an application, raise specific exceptions. Raising a generic exception makes your code brittle for error handling by downstream developers. You want your calling functions/methods to be able to handle exceptions and hopefully without their own specific checks around your library’s function.

Never Log and Re-Throw an Exception

Here’s an example where you carelessly casted a long integer as a string and perform the “catch and throw” anti-pattern. I’ve seen this a lot in Java code for some reason, so here it is:
try {
 new Long("some_string");
} catch (NumberFormatException e) {
 log.error(e);
 throw e;
}

The problem is you get multiple errors for the same exception; it’s just ambiguous and unnecessary. The extra stack trace doesn’t add any new information, other then to expose the entire Java stack that called it.
17:44:28,945 ERROR TestExceptionHandling:65 - java.lang.NumberFormatException: For input string: "some_string"
Exception in thread "main" java.lang.NumberFormatException: For input string: "some_string"
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.lang.Long.parseLong(Long.java:589)
	at java.lang.Long.(Long.java:965)
	at com.stackify.example.TestExceptionHandling.logAndThrowException(TestExceptionHandling.java:63)
	at com.stackify.example.TestExceptionHandling.main(TestExceptionHandling.java:58)

If you want to add a stack trace with the error, throw a custom exception that has useful information for your logging library:
public void wrapException(String input) throws CrazyCustomException {
 try {
 	 // do something
 } catch (NumberFormatException e) {
 	 throw new CrazyCustomException("I think you did something bad.", e);
 }
}

Handling Frontend Exceptions

A lot of frontend applications are designed with an optimistic approach of assuming a backend always works, but that’s never a 100% guarantee. Even bug-free backends run on systems infrastructure that will eventually fail. I’ve been a systems engineer and site reliability engineer and seen so many failures in my career, that I expect all systems to fail, at least partially, sometime in their production life. Handling errors on the frontend is critical to user experience and functionality. How can a support staff understand and support a product when it breaks? How can QA make bug tickets if you don’t have anything to show when errors happen?

Types of Frontend Errors

Here are the usual errors you’ll see:
  • Backend availability errors: The system that a frontend consumes goes down for some reason. Likely a server crash, deployment or unexpected maintenance.
  • Authentication/authorization errors: This happens when a user doesn’t have permission.
  • Input errors: This happens if validation is missing in the frontend but gets caught or thrown by the backend. Could be input validation or unique constraint errors in a database, for example.
  • Unknown errors: Sometimes errors just happen. API 500 errors due to an unhandled code exception can always happen, because sometimes you just forget to predict where backend code fails.

How Frontends Break With Unhandled Backend Errors

Frontend apps usually have little in the way of handling the backend errors. I’ve seen the following modes of failure in JS webapps:
  • If the error happens during framework initialization, users may see a white page.
  • The framework stops working with no indication of why. The user tries an action again, but either the web page is locked up or nothing happens. The user refreshes the web page and hopefully gets a working application.
  • The framework keeps running but unexpected things happen. The user likely tries over and over, hopefully getting the response they want, but possibly causing unintended side effects on the backend. A terrible example would be hitting a payment gateway and getting double or triple charged!

Put Errors in Context For the User

You want to start by designing your backend to handle errors as gracefully as possible, to give something for the frontend to present to a user. When designing a REST API for instance, instead of just returning 500, check out the list of available HTTP codes in the Mozilla developer center. I also suggest returning a body instead of an empty document with error generation so the web application can “bubble up” messages to a user. Something like this is excellent:
{
 "error": {
	"code": 500,
	"reason": "Payment gateway timeout, try again later"
 }
}

An error like this is great, because your application can tell the user something useful. So if they contact you for support, you’ll know exactly where your app went wrong. This is way better than the classic “Oops! An error occurred!”

Frontend Error Handling is Vital

It’s best to tell a user what went wrong and hint at what will fix the error for them. Here are some keywords I’d use to let a user make sense of frontend errors.
  • Invalid input. If the backend had an input validation error, tell the user.
  • Try again later. Something broke, but maybe it’ll work later. This lets the user know that this problem isn’t their fault and might resolve.
  • Unknown error. Please contact support. Something broke badly, so maybe you should contact a support team so they can determine the next steps.
You should write your frontend to use json stringify to parse the backend errors and return with valid context and messaging for the user.
Mezmo, formerly LogDNA, is an observability platform to manage and take action on your data. It ingests, processes, and routes log data to fuel enterprise-level application development and delivery, security, and compliance use cases.
Learn More
The latest from LogDNA

Conclusion

Just keep in mind that errors always happen, perfect test coverage or not. The question is what will you do to handle them with excellence? Will your users be able to take action to save the user experience when errors occur? Will they have a good user experience even when the app fails? Make it easier for users to create helpful GitHub issues or send useful messages to a support team. When your junior developer reads a bug ticket, will it be clear what happened without having to spelunk through the entire codebase? Handling errors appropriately keeps our users happy.
Mezmo, formerly LogDNA, is an observability platform to manage and take action on your data. It ingests, processes, and routes log data to fuel enterprise-level application development and delivery, security, and compliance use cases.
Learn More
The latest from LogDNA
TRENDING STORIES
Jonathan has been a technologist for 14 years, with a focus on DevOps for half of that. He’s currently a site reliability engineer at LogDNA, where he contributes his expertise about Linux, Kubernetes, networking and cloud infrastructure.
Read more from Jonathan Kelley
LogDNA sponsored this post.
SHARE THIS STORY
TRENDING STORIES
TNS owner Insight Partners is an investor in: Pragma.
SHARE THIS STORY
TRENDING STORIES
TNS DAILY NEWSLETTER Receive a free roundup of the most recent TNS articles in your inbox each day.
The New Stack does not sell your information or share it with unaffiliated third parties. By continuing, you agree to our Terms of Use and Privacy Policy.