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 properties or null 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:

  1. Add fallback objects with ?? or || operators
  2. Set default parameters on functions that destructure arguments
  3. Validate API responses before destructuring
  4. Use loading states in components to prevent premature destructuring
  5. 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.

TrackJS is the easy way to monitor your JavaScript applications and fix production errors. TrackJS is provides detailed error monitoring and alerting to developers around the world at companies like 3M, Tidal, IKEA, Venmo, Allbirds, and Frontend Masters. TrackJS catches millions of errors from users everyday. Let's start catching yours.

Protect your JavaScript