Skip to main content
View

Error Handling

Memberstack provides a rich error handling system with structured error objects, utility functions for extracting error information, and a complete set of error codes for programmatic handling. Every error includes actionable suggestions to help you resolve issues quickly.

Quick Overview

All error utilities are exported directly from @memberstack/dom. Import them alongside any other methods you use.

Error Object Structure

When a Memberstack method fails, the thrown error contains structured information to help you handle it programmatically and display helpful messages to users.

// Every Memberstack error includes these fields:
{
  message: "The provided credentials are invalid.",  // Human-readable message
  code: "invalid-credentials",                       // Machine-readable error code
  statusCode: 401,                                   // HTTP status code
  category: "authentication",                        // Error category for grouping
  suggestions: [                                     // Actionable fix suggestions
    "Verify the email address is spelled correctly",
    "Check if Caps Lock is enabled"
  ],
  docsUrl: "https://docs.memberstack.com/..."        // Link to relevant docs
}
💡 Tip:
The suggestions array is especially useful for building user-facing error messages. Each suggestion is a plain-English action the user can take to resolve the issue.

Utility Functions

Memberstack exports helper functions for safely extracting information from error objects. These are safer than accessing properties directly because they handle cases where the error may not be a Memberstack error.

import {
  isErrorCode,
  getErrorMessage,
  getErrorCode,
  getErrorCategory,
  getErrorSuggestions,
  getErrorDocsUrl,
  formatErrorForUser,
  getErrorReport,
  isMemberstackError,
  ErrorCodes
} from '@memberstack/dom';

getErrorMessage(error)

Extracts the human-readable error message from any error object.

try {
  await memberstack.loginMemberEmailPassword({ email, password });
} catch (error) {
  const message = getErrorMessage(error);
  // "The provided credentials are invalid."

  // Display to user
  document.getElementById('error').textContent = message;
}

isErrorCode(error, code)

Checks if an error matches a specific error code. Use this with the ErrorCodes constant for type-safe error checking.

import { isErrorCode, ErrorCodes } from '@memberstack/dom';

try {
  await memberstack.signupMemberEmailPassword({ email, password });
} catch (error) {
  if (isErrorCode(error, ErrorCodes.EMAIL_ALREADY_EXISTS)) {
    // Suggest logging in instead
    showMessage("This email is already registered. Try logging in.");
  } else if (isErrorCode(error, ErrorCodes.INVALID_PASSWORD)) {
    showMessage("Password doesn't meet the requirements.");
  } else if (isErrorCode(error, ErrorCodes.INVALID_EMAIL)) {
    showMessage("Please enter a valid email address.");
  } else {
    showMessage(getErrorMessage(error));
  }
}

getErrorCategory(error)

Returns the error category, useful for grouping errors in your UI or logging.

const category = getErrorCategory(error);

switch (category) {
  case 'authentication':
    // Show login-related error UI
    break;
  case 'validation':
    // Highlight invalid form fields
    break;
  case 'payment':
    // Show payment-related error UI
    break;
  case 'authorization':
    // Show access denied message
    break;
  case 'not_found':
    // Show "not found" message
    break;
  case 'network':
    // Show "check your connection" message
    break;
}

// Available categories:
// 'authentication' | 'authorization' | 'validation' | 'not_found'
// 'conflict' | 'payment' | 'limit' | 'account'
// 'data_tables' | 'network' | 'unknown'

getErrorSuggestions(error)

Returns an array of actionable suggestions for resolving the error. These are plain-English strings suitable for displaying to end users.

const suggestions = getErrorSuggestions(error);
// ["Verify the email address is spelled correctly", "Check if Caps Lock is enabled"]

if (suggestions?.length) {
  suggestions.forEach(suggestion => {
    const li = document.createElement('li');
    li.textContent = suggestion;
    errorList.appendChild(li);
  });
}

formatErrorForUser(error)

Returns a concise, user-friendly message for the error — a curated message keyed off the error code (it does not append the suggestions list). This is the quickest way to show a helpful error to your users; pair it with getErrorSuggestions() if you also want to render actionable steps.

try {
  await memberstack.loginMemberEmailPassword({ email, password });
} catch (error) {
  const userMessage = formatErrorForUser(error);
  alert(userMessage);
  // Example output (a single curated sentence):
  // "Invalid email or password. Please check your credentials and try again."
}

isMemberstackError(error)

Type guard that checks if an error is a Memberstack error (as opposed to a network error, TypeError, etc.).

try {
  await memberstack.signupMemberEmailPassword({ email, password });
} catch (error) {
  if (isMemberstackError(error)) {
    // Safe to access .code, .category, .suggestions, etc.
    console.log('Memberstack error:', error.code, error.category);
  } else {
    // Network error, TypeError, or other non-Memberstack error
    console.error('Unexpected error:', error);
  }
}

getErrorReport(error)

Returns a detailed error report object with all available information. Useful for logging and debugging.

const report = getErrorReport(error);
// {
//   message: "The provided credentials are invalid.",
//   code: "invalid-credentials",
//   statusCode: 401,
//   category: "authentication",
//   suggestions: ["Verify the email...", "Check if Caps Lock..."],
//   docsUrl: "https://docs.memberstack.com/..."
// }

// Log to your error tracking service
errorTracker.captureError(report);

Error Codes Reference

Use the ErrorCodes constant for type-safe error code checking. All codes are accessible as properties on the ErrorCodes object.

import { ErrorCodes, isErrorCode } from '@memberstack/dom';

// Use with isErrorCode() for type-safe checking
if (isErrorCode(error, ErrorCodes.INVALID_CREDENTIALS)) {
  // handle invalid credentials
}

Authentication Errors

ErrorCodes ConstantCode ValueDescription
INVALID_CREDENTIALSinvalid-credentialsWrong email or password
INVALID_TOKENclient/invalid-tokenInvalid or expired auth token
MEMBER_NOT_FOUNDmember-not-foundNo member found with this email
INVALID_RESET_CODEinvalid-reset-codeInvalid or expired password reset code
INVALID_PASSWORDLESS_CODEinvalid-passwordless-login-codeInvalid or expired passwordless code
LOGIN_REQUIREDlogin-requiredMember must be logged in

Account & Social Login Errors

ErrorCodes ConstantCode ValueDescription
EMAIL_ALREADY_EXISTSemail-already-in-useEmail is already registered
USE_SOCIAL_LOGINuse-social-loginAccount registered via social provider
USE_EMAIL_LOGINuse-email-loginAccount registered with email/password
NO_PASSWORD_SETno-password-setMember doesn't have a password set
ACCOUNT_ALREADY_CONNECTEDaccount-already-connectedProvider already connected to this account
ACCOUNT_NOT_CONNECTEDaccount-not-connectedProvider not connected to this account
ACCOUNT_CONNECT_FAILEDaccount-connect-failedFailed to connect provider
ACCOUNT_CONNECT_REQUIRES_LOGINaccount-connect-requires-loginMust be logged in to connect a provider
ACCOUNT_SET_PASSWORD_FIRSTaccount-set-password-before-disconnectSet a password before disconnecting the only provider
ACCOUNT_NOT_FOUNDaccount-not-foundNo account found for this provider

Validation Errors

ErrorCodes ConstantCode ValueDescription
INVALID_EMAILinvalid-emailInvalid email format
INVALID_PASSWORDinvalid-passwordPassword doesn't meet requirements
PASSWORD_TOO_SHORTinvalid-password-too-shortPassword is too short (min 8 characters)
REQUIRED_FIELD_MISSINGrequired-field-missingA required field was not provided
INVALID_CAPTCHAinvalid-captchaCaptcha verification failed

Plan & Subscription Errors

ErrorCodes ConstantCode ValueDescription
PLAN_NOT_FOUNDplan-not-foundPlan ID doesn't exist
NO_PLAN_FOUNDno-plan-foundNo plan found for this member
ALREADY_HAS_PLANalready-have-planMember already has this plan
PLAN_NOT_FREEplan-not-freeCannot add a paid plan with addPlan()
PLAN_MEMBER_LIMIT_REACHEDplan-member-limit-reachedPlan has reached its member limit
PLAN_RESTRICTED_TO_ADMINplan-restricted-to-adminPlan can only be assigned by admin
DOMAIN_NOT_PERMITTEDdomain-not-permittedEmail domain not allowed for this plan
PRICE_NOT_AVAILABLEprice-no-longer-availablePrice is no longer available

Data Table Errors

ErrorCodes ConstantCode ValueDescription
DATA_TABLE_NOT_FOUNDdata-table-not-foundTable key doesn't exist
DATA_RECORD_NOT_FOUNDdata-record-not-foundRecord ID doesn't exist
INVALID_TABLE_KEYinvalid-table-keyInvalid table key format
UNIQUE_CONSTRAINT_VIOLATIONunique-constraint-violationDuplicate value in unique field
FIELD_LIMIT_EXCEEDEDfield-limit-exceededToo many fields in table
INVALID_FIELD_TYPEinvalid-field-typeWrong data type for field
INVALID_FIELD_VALUEinvalid-field-valueInvalid value for field

Other Errors

ErrorCodes ConstantCode ValueDescription
ACCESS_DENIEDaccess-deniedInsufficient permissions
INVALID_FILE_TYPEinvalid-file-typeUnsupported file type for upload
FILE_TOO_LARGEfile-size-too-largeFile exceeds size limit
APP_NOT_FOUNDapp-not-foundApplication not found for this key
TEST_MODE_LIMIT_REACHEDtest-mode-member-limit-reachedSandbox member limit reached
NETWORK_ERRORnetwork-errorNetwork connection issue
UNKNOWN_ERRORunknown-errorAn unexpected error occurred

Complete Example

Here's a full example showing how to use the error handling utilities together in a signup form.

import memberstack from '@memberstack/dom';
import {
  isErrorCode,
  ErrorCodes,
  getErrorMessage,
  getErrorCategory,
  getErrorSuggestions,
  formatErrorForUser,
  isMemberstackError
} from '@memberstack/dom';

async function handleSignup(email, password) {
  try {
    const result = await memberstack.signupMemberEmailPassword({
      email,
      password
    });
    // Success - redirect or update UI
    window.location.href = result.data.redirect || '/dashboard';
  } catch (error) {
    // Check for specific error codes
    if (isErrorCode(error, ErrorCodes.EMAIL_ALREADY_EXISTS)) {
      showError('This email is already registered. Would you like to log in instead?');
      showLoginLink();
      return;
    }

    if (isErrorCode(error, ErrorCodes.PASSWORD_TOO_SHORT)) {
      showError('Password must be at least 8 characters.');
      highlightField('password');
      return;
    }

    if (isErrorCode(error, ErrorCodes.INVALID_EMAIL)) {
      showError('Please enter a valid email address.');
      highlightField('email');
      return;
    }

    if (isErrorCode(error, ErrorCodes.TEST_MODE_LIMIT_REACHED)) {
      showError('Test mode member limit reached. Delete some test members or switch to live mode.');
      return;
    }

    // For any other error, show the formatted message with suggestions
    if (isMemberstackError(error)) {
      showError(formatErrorForUser(error));
    } else {
      // Non-Memberstack error (network issue, etc.)
      showError('Something went wrong. Please check your connection and try again.');
      console.error('Unexpected error:', error);
    }
  }
}

Framework Examples

React

import { useState } from 'react';
import { isErrorCode, ErrorCodes, getErrorMessage, getErrorSuggestions } from '@memberstack/dom';

function LoginForm({ memberstack }) {
  const [error, setError] = useState(null);
  const [suggestions, setSuggestions] = useState([]);

  async function handleLogin(e) {
    e.preventDefault();
    setError(null);
    setSuggestions([]);

    const formData = new FormData(e.target);

    try {
      await memberstack.loginMemberEmailPassword({
        email: formData.get('email'),
        password: formData.get('password')
      });
    } catch (err) {
      setError(getErrorMessage(err));
      setSuggestions(getErrorSuggestions(err) || []);
    }
  }

  return (
    <form onSubmit={handleLogin}>
      <input name="email" type="email" placeholder="Email" />
      <input name="password" type="password" placeholder="Password" />
      <button type="submit">Log In</button>

      {error && (
        <div className="error">
          <p>{error}</p>
          {suggestions.length > 0 && (
            <ul>
              {suggestions.map((s, i) => <li key={i}>{s}</li>)}
            </ul>
          )}
        </div>
      )}
    </form>
  );
}

Svelte 5

<script>
  import { getErrorMessage, getErrorSuggestions, isErrorCode, ErrorCodes } from '@memberstack/dom';
  import { getMemberstack } from '$lib/memberstack';

  let error = $state(null);
  let suggestions = $state([]);

  async function handleLogin(email, password) {
    error = null;
    suggestions = [];
    const ms = getMemberstack();

    try {
      await ms.loginMemberEmailPassword({ email, password });
    } catch (err) {
      error = getErrorMessage(err);
      suggestions = getErrorSuggestions(err) || [];
    }
  }
</script>

{#if error}
  <div class="error">
    <p>{error}</p>
    {#if suggestions.length > 0}
      <ul>
        {#each suggestions as suggestion}
          <li>{suggestion}</li>
        {/each}
      </ul>
    {/if}
  </div>
{/if}

Need Help?

Having trouble getting your login working? We're here to help!

Thank you for choosing Memberstack 🙏