← Debugging Guides

阅读中文版本

Browser Uncaught (in promise) TypeError

Fix "Uncaught (in promise) TypeError" console errors by adding await, handling rejections, and validating response bodies before property access.

intermediatedebuggingbrowserjavascriptasync

Symptoms

  • Uncaught (in promise) TypeError: Cannot read properties of undefined
  • The console error appears after a delay with no stack in application code
  • Errors show even when a try/catch wraps the call

Possible causes

  • A promise rejection is not handled because the call site lacks await or .catch
  • A property is read from an undefined response field
  • An async event handler swallows the returned promise
  • response.json() resolves to an error object without the expected field

Diagnosis steps

Expand the console error to find the originating promise

Interpretation

Chrome links to the async stack; the top frame names the unhandled call.

Check that the async caller awaits or catches

Interpretation

An async function returns a promise that must be awaited or caught by its caller.

Log the resolved value before accessing properties

Interpretation

If the field is undefined, the payload shape differs from what the code assumes.

Root cause

An async function returns a promise; if nothing awaits it or attaches a catch, a rejection becomes an unhandled promise rejection reported as "Uncaught (in promise)". The TypeError itself is a downstream bug — reading a property of undefined — but the missing handler is why it escapes the surrounding try/catch.

Fix

Await async calls and handle rejections at the boundary, add .catch for fire-and-forget promises, and validate response bodies with optional chaining or a guard before reading fields. Wrap async event handlers so their returned promise is handled, and return a structured error rather than a payload missing expected fields.

Verify the fix

Reproduce the failing action; the console shows either a handled error or the correct data, and no "Uncaught (in promise)" appears while the UI reflects success or a controlled error state.

Symptoms

The console logs Uncaught (in promise) TypeError, often with a delay and a stack that starts inside framework code. A try/catch around the call seems ineffective.

Diagnosis

Follow the async stack and log the value before property access:

async function load() {
  const res = await fetch('/api/user');   // no catch
  const data = await res.json();
  console.log(data);                       // inspect shape
  return data.profile.name;                // TypeError if profile missing
}
load(); // returned promise unhandled

Fix

Handle rejections and validate shapes:

async function load() {
  try {
    const data = await (await fetch('/api/user')).json();
    return data?.profile?.name ?? 'anonymous';
  } catch (err) {
    console.error('load failed', err);
    return null;
  }
}
await load(); // or void load().catch(...)

Verification

Trigger the action again; the console has no unhandled promise error, and the UI shows either the data or a controlled error state.

Additional Notes

The unhandled rejection usually surfaces only in production because development builds fail loudly at the first error while a warmed-up bundle keeps resolving a stale promise. Enable the browser setting that pauses on uncaught exceptions, and make sure every async function invoked from a DOM event is wrapped so its rejection is caught at the boundary. Structured logging that records the call site and the resolved value turns an opaque promise error into a reproducible case, and a global unhandledrejection listener during development catches the ones that slip past component-level handlers.