Skip to main content

Errors in async functions

1. The basic principle

Errors inside async functions automatically turn into a rejected promise (Promise.reject).

So you handle them either with:

  • a try...catch block,
  • or the .catch() method on the returned promise.

2. Example with try...catch (the main approach)

javascript
async function getData() { try { const res = await fetch("https://no-such-domain.com"); const data = await res.json(); console.log(data); } catch (error) { console.error("An error occurred:", error.message); } } getData();

Output:

javascript
An error occurred: fetch failed

Here try...catch works just like it does in synchronous code, but it catches errors from every await inside it.


3. Why this works

await "pauses" the function until the promise settles. If the promise is rejected, await throws an exception, and control passes to catch.

Example:

javascript
async function example() { const result = await Promise.reject("Error!"); console.log(result); // never runs } example().catch(console.error);

Output:

javascript
Error!

4. An error without try...catch: the promise gets rejected

If you don't wrap await in try...catch, the function simply returns a rejected promise, which you can handle with .catch():

javascript
async function fail() { throw new Error("Something went wrong"); } fail().catch(err => console.error("Caught:", err.message));

Output:

javascript
Caught: Something went wrong

This is equivalent to handling .catch() on regular promises.


5. Several awaits, one try zone

You can wrap several awaits in a single try if you want to handle all the errors the same way:

javascript
async function loadUserData() { try { const user = await fetch("/api/user"); const posts = await fetch("/api/posts"); const comments = await fetch("/api/comments"); } catch (e) { console.error("Error loading data:", e); } }

If any of the operations fails, control immediately jumps to catch.


6. A local try for fine-grained control

Sometimes it's better to wrap individual awaits if you want to handle errors differently for each:

javascript
async function example() { try { const user = await fetchUser(); } catch (e) { console.error("Error loading the user:", e); } try { const posts = await fetchPosts(); } catch (e) { console.error("Error loading posts:", e); } }

7. Example: "healing" an error (like .catch().then())

If you return a value from catch, the function continues running:

javascript
async function example() { try { await Promise.reject("Error!"); } catch (e) { console.log("Caught:", e); return "Default value"; } } example().then(result => console.log("Result:", result));

Output:

javascript
Caught: Error! Result: Default value

8. Errors in parallel awaits (Promise.all)

If you run several awaits in parallel through Promise.all, and at least one of the promises rejects, the whole Promise.all fails.

javascript
async function parallel() { try { const [a, b] = await Promise.all([ Promise.resolve("ok"), Promise.reject("error"), ]); } catch (e) { console.log("Caught:", e); } } parallel();

Output:

javascript
Caught: error

9. Using catch directly (an alternative to try...catch)

javascript
async function getUser() { const res = await fetch("/api/user").catch(err => { console.error("Error during the request:", err); return null; // return a safe fallback value }); console.log("Result:", res); } getUser();

This approach is often used when you just need to "suppress" an error and let the program continue.


10. Best practices

SituationWhat to use
Handling errors inside one functiontry...catch
Handling errors when calling an async function.catch()
Different error types with different reactionsSeveral try...catch blocks
Several parallel awaitsPromise.allSettled() instead of Promise.all
Logging and rethrowingcatch (e) { log(e); throw e; }

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.