Skip to content
Back to skills

1570 Gotchas Eb07fbd1

ASecurity

**Cause:** Auth token invalid/expired, API credentials lack permissions, or network blocks WebRTC **Solution:** Verify token validity, check API token has **Realtime / Realtime Admin** permissions, enable TURN service for restrictive networks

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
developmenttypescriptgoreactdebuggingapidatabasefrontendbackendsecurityperformance

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 1570-gotchas_eb07fbd1 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 1570 Gotchas Eb07fbd1?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 1570 Gotchas Eb07fbd1
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-1570-gotchas-eb07fbd1/badge)](https://www.skillsdirectory.com/skills/tools-only-1570-gotchas-eb07fbd1)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# RealtimeKit Gotchas & Troubleshooting

## Common Errors

### "Cannot connect to meeting"

**Cause:** Auth token invalid/expired, API credentials lack permissions, or network blocks WebRTC
**Solution:**
Verify token validity, check API token has **Realtime / Realtime Admin** permissions, enable TURN service for restrictive networks

### "No video/audio tracks"

**Cause:** Browser permissions not granted, video/audio not enabled, device in use, or device unavailable
**Solution:**
Request browser permissions explicitly, verify initialization config, use `meeting.self.getAllDevices()` to debug, close other apps using device

### "Participant count mismatched"

**Cause:** `meeting.participants` doesn't include `meeting.self`
**Solution:** Total count = `meeting.participants.joined.size() + 1`

### "Events not firing"

**Cause:** Listeners registered after actions, incorrect event name, or wrong namespace
**Solution:**
Register listeners before calling `meeting.join()`, check event names against docs, verify correct namespace

### "CORS errors in API calls"

**Cause:** Making REST API calls from client-side
**Solution:** All REST API calls **must** be server-side (Workers, backend). Never expose API tokens to clients.

### "Preset not applying"

**Cause:** Preset doesn't exist, name mismatch (case-sensitive), or participant created before preset
**Solution:**
Verify preset exists via Dashboard or API, check exact spelling and case, create preset before adding participants

### "Token reuse error"

**Cause:** Reusing participant tokens across sessions
**Solution:** Generate fresh token per session. Use refresh endpoint if token expires during session.

### "Video quality poor"

**Cause:** Insufficient bandwidth, resolution/bitrate too high, or CPU overload
**Solution:**
Lower `mediaConfiguration.video` resolution/frameRate, monitor network conditions, reduce participant count or grid size

### "Echo or audio feedback"

**Cause:** Multiple devices picking up same audio source
**Solution:**

- Lower `mediaConfiguration.video` resolution/frameRate
- Monitor network conditions
- Reduce participant count or grid size

### Issue: Echo or audio feedback

**Cause**: Multiple devices picking up same audio source

**Solutions**:
Enable `echoCancellation: true` in `mediaConfiguration.audio`, use headphones, mute when not speaking

### "Screen share not working"

**Cause:** Browser doesn't support screen sharing API, permission denied, or wrong `displaySurface` config
**Solution:**
Use Chrome/Edge/Firefox (Safari limited support), check browser permissions, try different `displaySurface` values ('window', 'monitor', 'browser')

### "How do I schedule meetings?"

**Cause:** RealtimeKit has no built-in scheduling system
**Solution:**
Store meeting IDs in your database with timestamps. Generate participant tokens only when user should join. Example:

```typescript
// Store in DB
{ meetingId: 'abc123', scheduledFor: '2026-02-15T10:00:00Z', userId: 'user456' }

// Generate token when user clicks "Join" near scheduled time
const response = await fetch('/api/join-meeting', {
  method: 'POST',
  body: JSON.stringify({ meetingId: 'abc123' })
});
const { authToken } = await response.json();
```

### "Recording not starting"

**Cause:** Preset lacks recording permissions, no active session, or API call from client
**Solution:**
Verify preset has `canRecord: true` and `canStartStopRecording: true`, ensure session is active (at least one participant), make recording API calls server-side only

## Limits

| Resource                        | Limit              |
| ------------------------------- | ------------------ |
| Max participants per session    | 100                |
| Max concurrent sessions per App | 1000               |
| Max recording duration          | 6 hours            |
| Max meeting duration            | 24 hours           |
| Max chat message length         | 4000 characters    |
| Max preset name length          | 64 characters      |
| Max meeting title length        | 256 characters     |
| Max participant name length     | 256 characters     |
| Token expiration                | 24 hours (default) |
| WebRTC ports required           | UDP 1024-65535     |

## Network Requirements

### Firewall Rules

Allow outbound UDP/TCP to:

- `*.cloudflare.com` ports 443, 80
- UDP ports 1024-65535 (WebRTC media)

### TURN Service

Enable for users behind restrictive firewalls/proxies:

```jsonc
// wrangler.jsonc
{
  "vars": {
    "TURN_SERVICE_ID": "your_turn_service_id",
  },
  // Set secret: wrangler secret put TURN_SERVICE_TOKEN
}
```

TURN automatically configured in SDK when enabled in account.

## Debugging Tips

```typescript
// Check devices
const devices = await meeting.self.getAllDevices()
meeting.self.on('deviceListUpdate', ({ added, removed, devices }) =>
  console.log('Devices:', { added, removed, devices }),
)

// Monitor participants
meeting.participants.joined.on('participantJoined', (p) =>
  console.log(`${p.name} joined:`, {
    id: p.id,
    userId: p.userId,
    audioEnabled: p.audioEnabled,
    videoEnabled: p.videoEnabled,
  }),
)

// Check room state
meeting.self.on('roomJoined', () =>
  console.log('Room:', {
    meetingId: meeting.meta.meetingId,
    meetingTitle: meeting.meta.meetingTitle,
    participantCount: meeting.participants.joined.size() + 1,
    audioEnabled: meeting.self.audioEnabled,
    videoEnabled: meeting.self.videoEnabled,
  }),
)

// Log all events
;['roomJoined', 'audioUpdate', 'videoUpdate', 'screenShareUpdate', 'deviceUpdate', 'deviceListUpdate'].forEach(
  (event) => meeting.self.on(event, (data) => console.log(`[self] ${event}:`, data)),
)
;['participantJoined', 'participantLeft'].forEach((event) =>
  meeting.participants.joined.on(event, (data) => console.log(`[participants] ${event}:`, data)),
)
meeting.chat.on('chatUpdate', (data) => console.log('[chat] chatUpdate:', data))
```

## Security & Performance

### Security: Do NOT

- Expose `CLOUDFLARE_API_TOKEN` in client code, hardcode credentials in frontend
- Reuse participant tokens, store tokens in localStorage without encryption
- Allow client-side meeting creation

### Security: DO

- Generate tokens server-side only, use HTTPS, implement rate limiting
- Validate user auth before generating tokens, use `custom_participant_id` to map to your user system
- Set appropriate preset permissions per user role, rotate API tokens regularly

### Performance

- **CPU**: Lower video resolution/frameRate, disable video for audio-only, use `meeting.participants.active` for large meetings, implement virtual scrolling
- **Bandwidth**: Set max resolution in `mediaConfiguration`, disable screenshare audio if unneeded, use audio-only mode, implement adaptive bitrate
- **Memory**: Clean up event listeners on unmount, call `meeting.leave()` when done, don't store large participant arrays

## In This Reference

- [README.md](README.md) - Overview, core concepts, quick start
- [configuration.md](configuration.md) - SDK config, presets, wrangler setup
- [api.md](api.md) - Client SDK APIs, REST endpoints
- [patterns.md](patterns.md) - Common patterns, React hooks, backend integration

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.