This is Safari’s way of telling you that you tried to destructure something that doesn’t exist. The error occurs when JavaScript attempts to extract properties from null or undefined using destructuring syntax. Since neither value has properties, the operation fails.
This error frequently appears in applications dealing with API responses, database queries, or any async data that might not be available when your code expects it.
Other browsers show the same error with different messages:
- Chrome/Edge/V8:
Cannot destructure property 'x' of 'y' as it is undefined. - Firefox:
undefined has no propertiesornull has no properties
The Problem
“Right side of assignment cannot be destructured” is a TypeError that occurs when you try to use destructuring assignment on null or undefined. JavaScript can only destructure objects and arrays, so attempting to extract properties from values that have no properties throws this error.
Here’s the classic scenario:
// API returns null when user not found
const userData = null;
// Safari throws: Right side of assignment cannot be destructured
const { name, email } = userData;
The error also occurs with undefined:
// Function called without arguments
function processUser({ name, email }) {
console.log(name, email);
}
// Safari throws: Right side of assignment cannot be destructured
processUser(); // No argument passed, so it's undefined
Key point: This error always means your code expected an object but received null or undefined instead. The fix is ensuring you have a valid object before destructuring.
Understanding the Root Cause
“Right side of assignment cannot be destructured” stems from several common patterns in modern JavaScript applications:
1. API Responses Returning Null
Most common cause: Backend APIs return null when requested data doesn’t exist, but your frontend code assumes it will always receive an object.
How to identify: Errors correlate with API calls, especially for optional or user-specific data like profiles, settings, or search results.
2. Missing Function Arguments
Functions that destructure their parameters fail when called without arguments, since missing parameters default to undefined.
How to identify: Stack traces point to function definitions with destructuring patterns in the parameter list.
3. Async Data Loading Race Conditions
React, Vue, and Angular components often try to destructure state or props before async data finishes loading.
How to identify: Errors occur during component mounting or immediately after page load, often disappearing after data loads.
4. DOM Query Results
Methods like document.querySelector() return null when no matching element exists. Destructuring these results fails.
How to identify: Errors occur when accessing element properties or dataset values from DOM queries.
5. Array Access Beyond Bounds
Accessing array indices that don’t exist returns undefined, which can’t be destructured.
How to identify: Errors happen when destructuring items from arrays that may be empty or shorter than expected.
6. Optional Object Properties
Nested destructuring fails when intermediate properties are null or undefined.
How to identify: Deep destructuring patterns like const { user: { profile: { name } } } where any level might be missing.
How to Fix “Right side of assignment cannot be destructured”
Quick Troubleshooting Checklist
- Add fallback empty objects using
??or||operators - Set default parameter values for function arguments
- Verify API response structure before destructuring
- Use optional chaining for property access when destructuring isn’t necessary
- Add loading state checks in React/Vue/Angular components
- Validate DOM query results before accessing properties
If basic checks don’t resolve the issue, follow these systematic fixes:
Step 1: Add Fallback Objects with Nullish Coalescing
The most reliable fix is providing an empty object fallback:
// Before: Crashes if userData is null or undefined
const { name, email } = userData;
// After: Safe destructuring with fallback
const { name, email } = userData ?? {};
// You can also use logical OR (works for all falsy values)
const { name, email } = userData || {};
The ?? operator only applies the fallback for null or undefined, while || applies it for any falsy value. For destructuring, ?? is usually the better choice.
Step 2: Set Default Function Parameters
Always provide defaults for function parameters that will be destructured:
// Before: Fails when called without arguments
function createUser({ name, email, role }) {
return { name, email, role };
}
// After: Safe with default empty object
function createUser({ name, email, role } = {}) {
return { name, email, role };
}
// Now these all work without errors
createUser(); // Returns { name: undefined, email: undefined, role: undefined }
createUser({ name: 'Alice' }); // Returns { name: 'Alice', email: undefined, role: undefined }
createUser({ name: 'Bob', role: 'admin' });
Step 3: Handle Nested Destructuring Safely
Nested destructuring is particularly fragile. Protect each level:
// Dangerous: Multiple points of failure
const { user: { profile: { name } } } = apiResponse;
// Safe approach: Fallbacks at each level
const { user } = apiResponse ?? {};
const { profile } = user ?? {};
const { name } = profile ?? {};
// Alternative: Use optional chaining instead of destructuring
const name = apiResponse?.user?.profile?.name;
Step 4: Validate API Responses
Add explicit checks for API data before destructuring:
async function fetchUserData(userId) {
const response = await fetch(`/api/users/${userId}`);
const data = await response.json();
// Validate response structure before destructuring
if (!data || typeof data !== 'object') {
console.warn('Invalid user data received:', data);
return null;
}
const { name, email, preferences } = data;
return {
name: name ?? 'Unknown User',
email: email ?? '',
preferences: preferences ?? {}
};
}
Step 5: Handle React Component State Properly
In React, always account for loading states:
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchUser(userId)
.then(data => setUser(data))
.finally(() => setLoading(false));
}, [userId]);
// Guard against destructuring null/undefined
if (loading) return <div>Loading...</div>;
if (!user) return <div>User not found</div>;
// Safe to destructure after validation
const { name, email, avatar } = user;
return (
<div>
<img src={avatar} alt={name} />
<h1>{name}</h1>
<p>{email}</p>
</div>
);
}
Step 6: Protect DOM Query Results
Always check DOM queries before destructuring their results:
// Dangerous: querySelector returns null if element doesn't exist
const { dataset: { userId } } = document.querySelector('.user-card');
// Safe: Check element exists first
const userCard = document.querySelector('.user-card');
const userId = userCard?.dataset?.userId;
// Or with explicit validation
const userCard = document.querySelector('.user-card');
if (userCard) {
const { dataset: { userId, userRole } } = userCard;
initializeUser(userId, userRole);
}
Step 7: Monitor for Production Errors
Destructuring errors often only appear in production when real users encounter edge cases your tests didn’t cover. Error monitoring services like TrackJS capture these errors with full context about which destructuring operation failed and what the actual value was.
This visibility helps you identify patterns like specific API endpoints returning unexpected data or certain user flows that hit edge cases more frequently.
When to Ignore This Error
This error should rarely be ignored since it indicates real problems with data flow. However, consider the context:
- Third-party library bugs: Some libraries may throw this error internally with their own error handling
- Development hot reload: Temporary errors during fast refresh cycles
- Browser extension interference: Extensions modifying page data
Investigate further when you see:
- User-facing impact: Broken pages or missing content
- Consistent patterns: Same destructuring operation failing repeatedly
- Core functionality: Errors affecting checkout, authentication, or data submission
- Sudden increases: Spikes after API changes or deployments
Summary
“Right side of assignment cannot be destructured” is Safari’s error message when you try to destructure null or undefined. Chrome shows “Cannot destructure property” and Firefox shows “undefined has no properties” for the same underlying issue.
The fix is always about ensuring you have a valid object before destructuring:
- Add fallback objects with
??or||operators - Set default parameters on functions that destructure arguments
- Validate API responses before destructuring
- Use loading states in components to prevent premature destructuring
- Check DOM queries return elements before accessing their properties
Remember: Destructuring is convenient syntax, but it assumes your data exists. When working with data that might be missing, either add explicit fallbacks or use optional chaining instead.