The Exact Error
TypeError: Cannot convert undefined or null to object
Or:
TypeError: Cannot convert undefined to object (Object.keys called on non-object)
TypeError: null is not an object (evaluating 'Object.keys(data)')
Quick summary:
Object.keys(),Object.values(), orObject.entries()was called withnullorundefined. These methods require an actual object. The data either hasn't loaded yet, the API returned null, or the object was accessed at the wrong nesting level.
Why This Error Happens
Object.keys(x) converts x to an object internally. The ECMAScript ToObject() operation throws a TypeError for null and undefined.
Five root causes:
1. Async timing ? Calling Object.keys(data) before an API response arrives. Initial state is null.
2. API returning null ? Backend returns null instead of {} when a record doesn't exist.
3. Wrong property access ? Object.keys(response.data) when the actual data is at response.body.data.
4. Optional chaining result ? Object.keys(user?.preferences) ? if user?.preferences returns undefined, this throws.
5. Destructuring with missing keys ? const { settings } = apiResponse ? if settings doesn't exist, it's undefined.
Step-by-Step Diagnosis
Step 1 ? Log the value before the call
console.log('data value:', data);
console.log('data type:', typeof data);
Object.keys(data); // Error here
Step 2 ? Check initial state
const [userData, setUserData] = useState(null); // null initial state!
Object.keys(userData) // Throws on first render
Step 3 ? Check optional chaining results
const prefs = user?.preferences; // undefined if user is null
Object.keys(prefs); // TypeError!
Solutions
Solution 1 ? Use nullish coalescing fallback
const keys = Object.keys(data ?? {});
const values = Object.values(data ?? {});
const entries = Object.entries(data ?? {});
Solution 2 ? Add an explicit null check
if (data != null) {
const keys = Object.keys(data);
}
Solution 3 ? Initialize state as an empty object
const [config, setConfig] = useState({});
// Object.keys(config) always works
Solution 4 ? Normalize API response at fetch time
async function fetchUserConfig(userId) {
const response = await fetch(`/api/users/${userId}/config`);
const json = await response.json();
return json?.config ?? {}; // Always returns an object
}
Solution 5 ? TypeScript compile-time check
// With strictNullChecks: true:
const [config, setConfig] = useState<UserConfig | null>(null);
if (config !== null) {
Object.keys(config); // TypeScript narrows to UserConfig
}
Quick Reference
| Situation | Safe pattern |
|---|---|
| Maybe-null from API | Object.keys(data ?? {}) |
| Initial state before load | useState({}) |
| Optional chain result | obj ? Object.keys(obj) : [] |
| Destructured missing property | const { settings = {} } = response |
Prevent This Error in the Future
1. Default destructured values at the source. Use const { settings = {} } = response.
2. Normalize every API response before storing in state ? convert null to {}.
3. Enable strictNullChecks: true in TypeScript.
Use ToolNinja to Debug Faster
When Object.keys() throws because the API returned an unexpected shape, the JSON to TypeScript converter shows exactly what type your API is returning ? including which fields can be null.
?? JSON to TypeScript ? toolninja.io/tools/json-to-typescript