# TypeError: “Cannot convert undefined or null to object”

> TypeError: Cannot convert undefined or null to object. Object.keys, entries, values or assign got undefined or null. Default the value or wait for the data.

Canonical: https://app369.com/fix/cannot-convert-undefined-or-null-to-object/
Last updated: 2026-11-08

Code fails with TypeError: Cannot convert undefined or null to object (Firefox: can't convert undefined to object), with a stack trace into Object.keys, Object.entries, Object.values or Object.assign. Those functions need an object, and the value passed was undefined or null, usually because data had not loaded or a field was missing.

**Short answer**

Find the Object.keys, Object.entries, Object.values or Object.assign call in the stack trace and log the value passed to it. Give it a fallback, Object.keys(data ?? {}), or return early until the data exists. For Object.assign, the first argument (the target) must be an object: use Object.assign({}, a, b) or the spread syntax { ...a, ...b }, which skips undefined and null without throwing.

## **Why the value is not an object, and the fix**

1. 01 ### **Object.keys, entries or values on missing data**
  > “undefined and null cannot be coerced to objects and throw a TypeError upfront.” [**MDN, Object.keys(): using Object.keys() on primitives**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) Data from an API, a database or component props is undefined on the first render, or null when the record does not exist. Fall back to an empty object, or wait until the data has loaded.```
const rows = Object.entries(stats ?? {});

if (!user) return; // or render a loading state
const fields = Object.keys(user);
```
2. 02 ### **Object.assign with an undefined target** Object.assign(target, ...sources) throws when the target is undefined or null. Sources that are undefined or null are skipped. Start from a new object, or use the spread syntax.```
const settings = Object.assign({}, defaults, saved);
const merged = { ...defaults, ...saved }; // saved can be undefined
```
3. 03 ### **A field that is optional in the data** An API that leaves out a nested object when it is empty (for example metadata or options) breaks code that always expects it. Use optional chaining and a default where you read it.```
const tags = Object.keys(post.metadata?.tags ?? {});
```

Checked against the vendor’s docs on November 8, 2026: [MDN: Object.keys()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys).

## **Rather hand it over?**

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

- [from $450**App Fix Ticket**One reproducible bug in an existing mobile or web app, diagnosed and fixed.**See scope and start**](https://app369.com/fixed-price/flutter-firebase-bug-fix/)
- [from $450**AI-Built App Rescue**A Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.****No issues worth fixing, no charge.**** If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.**See scope and start**](https://app369.com/fixed-price/ai-app-rescue/)

Related: [**“Cannot read properties of undefined”**](https://app369.com/fix/cannot-read-properties-of-undefined/) · [**“Cannot destructure property”**](https://app369.com/fix/cannot-destructure-property/) · [**TypeError: “x is not a constructor”**](https://app369.com/fix/is-not-a-constructor/)

Questions

## **More on this error**

<details>

<summary>**Why does Object.keys work on a string or number but not on null? **+</summary>

Strings and numbers are converted to wrapper objects first. undefined and null have no wrapper object, so they throw instead.

</details>

<details>

<summary>**Should I wrap it in try/catch? **+</summary>

No. A fallback value or an early return is clearer and does not hide other errors in the same block.

</details>

<details>

<summary>**Can you fix it for me? **+</summary>

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.

</details>

A different error?

## **Describe it and get a written quote**

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; Simon replies by email, usually within one business day.

[**Describe your problem **→](https://app369.com/contact/) [**All fixes**](https://app369.com/fix/)