Skip to main content

Error Handling

Error Handling

Reducers distinguish between two types of errors:

Sender Errors

Errors caused by invalid client input. These are expected and should be handled gracefully.

Throw a SenderError:

import { SenderError } from 'spacetimedb/server';

spacetimedb.reducer('transfer_credits', 
  { to_user: t.u64(), amount: t.u32() },
  (ctx, { to_user, amount }) => {
    const fromUser = ctx.db.users.id.find(ctx.sender);
    if (!fromUser) {
      throw new SenderError('User not found');
    }
    
    if (fromUser.credits < amount) {
      throw new SenderError('Insufficient credits');
    }
    
    // ... perform transfer
  }
);

// Alternative: return error object
spacetimedb.reducer('transfer_credits',
  { to_user: t.u64(), amount: t.u32() },
  (ctx, { to_user, amount }) => {
    // ...validation...
    if (error) {
      return { tag: 'err', value: 'Insufficient credits' };
    }
    // ...
  }
);

Programmer Errors

Unexpected errors caused by bugs in module code. These should be fixed by the developer.

Regular errors (not SenderError):

spacetimedb.reducer('process_data', 
  { data: t.array(t.u8()) },
  (ctx, { data }) => {
    // Regular Error indicates a bug
    if (data.length === 0) {
      throw new Error('Unexpected empty data');
    }
    
    // ...
  }
);

Programmer errors are logged and visible in your project dashboard. Consider setting up alerting to be notified when these occur.