Thanks to visit codestin.com
Credit goes to sonicjs.com

Troubleshooting Guide

Diagnose and resolve common issues in SonicJS applications with this comprehensive troubleshooting guide.


Overview

This guide covers the most common issues developers encounter when working with SonicJS, organized by category with specific error messages and solutions.


Authentication Errors

401 - Authentication Required

Error Message: "Authentication required" or "Invalid or expired token"

Causes:

  • Missing JWT token in request
  • Token not in Authorization header or auth_token cookie
  • Malformed Bearer token format

Solutions:

Check Token Format

// Correct format - Authorization header
fetch('/api/content', {
  headers: {
    'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
  }
})

// Or use cookies (set by login endpoint)
fetch('/api/content', {
  credentials: 'include'  // Include cookies in request
})

401 - Expired Token

Error Message: "Your session has expired, please login again"

Causes:

  • Token's exp timestamp has passed
  • Default token lifetime is 24 hours

Solutions:

Refresh Token

// Call refresh endpoint before token expires
const response = await fetch('/auth/refresh', {
  method: 'POST',
  credentials: 'include'
})

if (response.ok) {
  // New token automatically set in cookie
  console.log('Token refreshed')
} else {
  // Redirect to login
  window.location.href = '/admin/login'
}

403 - Insufficient Permissions

Error Message: "Insufficient permissions"

Causes:

  • User role doesn't match required role for endpoint
  • Trying to access admin endpoints without admin role

Solutions:

  1. Verify the user has the correct role assigned
  2. Check the endpoint's required role in the route definition
  3. Use the correct role when creating users:

User Roles

// Available roles (most to least privileged)
const roles = ['admin', 'editor', 'author', 'viewer']

// Create user with specific role
await db.prepare(`
  INSERT INTO users (email, password, role)
  VALUES (?, ?, ?)
`).bind(email, hashedPassword, 'editor').run()

Login Failures

Error Message: "Invalid email or password"

Causes:

  • Incorrect password
  • Email not found in database
  • Email case sensitivity issues

Solutions:

  1. Verify email is normalized to lowercase
  2. Check password meets minimum requirements (8+ characters)
  3. Use password reset if credentials are lost

Email Normalization

// SonicJS normalizes emails to lowercase
const normalizedEmail = email.toLowerCase().trim()

// Ensure consistency when checking credentials

Database Errors

409 - Duplicate Content Slug

Error Message: "A content item with this slug already exists in this collection"

Causes:

  • Attempting to create content with a slug that already exists
  • Slug uniqueness is enforced per collection

Solutions:

Generate Unique Slug

// Auto-generate unique slug
function generateUniqueSlug(title: string, existingSlugs: string[]): string {
  let slug = title
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/(^-|-$)/g, '')

  let counter = 1
  let uniqueSlug = slug

  while (existingSlugs.includes(uniqueSlug)) {
    uniqueSlug = `${slug}-${counter}`
    counter++
  }

  return uniqueSlug
}

400 - Duplicate User

Error Message: "User with this email or username already exists"

Causes:

  • Email already registered
  • Username already taken

Solutions:

  1. Check if user exists before registration
  2. Provide clear feedback to users about which field is duplicate

Check Existing User

// Check before registration
const existing = await db
  .prepare('SELECT id FROM users WHERE email = ? OR username = ?')
  .bind(email.toLowerCase(), username)
  .first()

if (existing) {
  return c.json({ error: 'User already exists' }, 400)
}

404 - Content Not Found

Error Message: "Content not found"

Causes:

  • Invalid content ID
  • Content was deleted
  • Looking in wrong collection

Solutions:

  1. Verify the content ID is correct
  2. Check that content hasn't been soft-deleted
  3. Ensure you're querying the correct collection

UNIQUE Constraint Failed

Error Message: "UNIQUE constraint failed: [table].[column]"

Causes:

  • Database-level uniqueness violation
  • Migration re-running with existing data

Solutions:

Handle Constraint Errors

try {
  await db.prepare('INSERT INTO users (email) VALUES (?)').bind(email).run()
} catch (error) {
  if (error.message.includes('UNIQUE constraint failed')) {
    // Handle duplicate gracefully
    return c.json({ error: 'Email already exists' }, 400)
  }
  throw error
}

Cache Issues

Cache Not Working

Symptoms:

  • Data not being cached
  • Stale data being served
  • High database load

Causes:

  • KV binding not configured
  • Cache disabled in settings
  • Cache keys not matching

Solutions:

Verify Cache Configuration

# wrangler.toml - Ensure KV binding exists
[[kv_namespaces]]
binding = "CACHE_KV"
id = "your-kv-namespace-id"

Check Cache Status

// Verify cache is working
const cacheService = new CacheService(env.CACHE_KV)

// Test cache operations
await cacheService.set('test-key', { value: 'test' }, 60)
const result = await cacheService.get('test-key')

if (!result) {
  console.error('Cache write/read failed')
}

Cache Invalidation Issues

Symptoms:

  • Old data persists after updates
  • Changes not reflected immediately

Solutions:

  1. Content updates automatically invalidate related cache keys
  2. Force invalidation after custom operations:

Manual Cache Invalidation

import { CacheInvalidationService } from '@sonicjs-cms/core/plugins'

const invalidation = new CacheInvalidationService(env.CACHE_KV)

// Invalidate content cache
await invalidation.invalidateContent(contentId)

// Invalidate user cache
await invalidation.invalidateUser(userId)

// Invalidate collection cache
await invalidation.invalidateCollection(collectionId)

Memory Cache Overflow

Symptoms:

  • Memory usage increasing
  • Worker crashes on memory limits

Solutions:

  • Memory cache defaults to 50MB limit with LRU eviction
  • Use KV cache for production workloads
  • Configure appropriate TTLs:

Cache TTL Configuration

// Short TTL for frequently changing data
await cache.set('user-session', data, 300)  // 5 minutes

// Longer TTL for stable content
await cache.set('collection-schema', schema, 3600)  // 1 hour

// Very long TTL for static assets
await cache.set('site-config', config, 86400)  // 24 hours

Email & Notification Errors

Email Plugin Not Available

Error Message: "Email plugin not available"

Causes:

  • Email plugin not enabled
  • SendGrid API key not configured

Solutions:

Configure Email

# wrangler.toml
[vars]
DEFAULT_FROM_EMAIL = "[email protected]"
DEFAULT_FROM_NAME = "Your App"

# Set API key as secret
# npx wrangler secret put SENDGRID_API_KEY

OTP Email Failed

Error Message: "Failed to send OTP email" or "Error sending OTP email"

Causes:

  • Email service not configured
  • SendGrid API key invalid
  • From email not verified in SendGrid

Solutions:

  1. Verify SendGrid API key has Mail Send permission
  2. Verify sender domain/email in SendGrid
  3. Check email plugin is enabled:

Enable Email Plugin

// In admin: Plugins > Enable Email Templates
// Or programmatically:
const settings = await getPluginSettings('email-templates')
console.log('Email enabled:', settings.enabled)

Email Template Not Found

Causes:

  • Template slug doesn't exist
  • Template is inactive

Solutions:

Check Template

// List available templates
const templates = await db
  .prepare('SELECT slug, name, is_active FROM email_templates')
  .all()

console.log('Available templates:', templates.results)

// Ensure template is active
await db
  .prepare('UPDATE email_templates SET is_active = 1 WHERE slug = ?')
  .bind('welcome-email')
  .run()

Plugin Errors

Plugin Installation Failed

Error Message: "Failed to install plugin [name]"

Causes:

  • Invalid plugin configuration
  • Conflicting table names
  • Reserved plugin name used

Solutions:

Validate Plugin

import { PluginValidator } from '@sonicjs-cms/core/plugins'

const validation = PluginValidator.validate(myPlugin)

if (!validation.valid) {
  console.error('Plugin validation errors:', validation.errors)
  // Fix issues before installing
}

Reserved Names

Reserved plugin names (cannot be used):

  • core, system, admin, api, auth, content, media, users, collections

Reserved table names (cannot be used by plugins):

  • users, collections, content, content_versions, media, api_tokens

Plugin Name Validation

Error Message: "Invalid plugin name"

Requirements:

  • Must match pattern: /^[a-z0-9-]+$/
  • Lowercase letters, numbers, and hyphens only
  • No spaces or special characters

Valid Plugin Names

// Valid
'my-plugin'
'analytics-v2'
'custom-auth'

// Invalid
'MyPlugin'      // No uppercase
'my plugin'     // No spaces
'my_plugin'     // No underscores

Hook Recursion Detected

Error Message: "Hook recursion detected"

Causes:

  • Hook handler triggers the same hook
  • Circular hook dependencies

Solutions:

Prevent Recursion

// Bad - causes recursion
hooks.register('content:save', async (data) => {
  // This triggers content:save again!
  await db.prepare('UPDATE content SET ...').run()
  return data
})

// Good - use flag to prevent recursion
hooks.register('content:save', async (data, context) => {
  if (context.fromHook) return data

  // Safe to update with flag
  await db.prepare('UPDATE content SET ...').run()
  return data
})

Collection Errors

Invalid Collection Config

Error Message: "Invalid collection config: missing required fields"

Required fields:

  • name - Collection identifier
  • displayName - Human-readable name
  • schema - Field definitions

Valid Collection Config

import { defineCollection } from '@sonicjs-cms/core'

export default defineCollection({
  name: 'blog_posts',          // Required
  displayName: 'Blog Posts',   // Required
  schema: {                    // Required
    title: { type: 'string', required: true },
    content: { type: 'richtext' }
  }
})

Collection Name Validation

Error Message: "Collection name must contain only lowercase letters, numbers, underscores, and hyphens"

Requirements:

  • Must match pattern: /^[a-z0-9_-]+$/
  • No uppercase letters
  • No spaces

Valid Collection Names

// Valid
'blog_posts'
'user-profiles'
'faq'

// Invalid
'BlogPosts'      // No uppercase
'blog posts'     // No spaces
'blog.posts'     // No dots

Bootstrap & Startup

Bootstrap Errors

Symptoms:

  • App starts but features don't work
  • Collections not synced
  • Migrations not applied

Solutions:

Bootstrap errors are caught but logged. Check console for:

  • Collection sync failures
  • Migration errors
  • Plugin initialization failures

Manual Bootstrap

// Force re-bootstrap on specific errors
import { runMigrations } from '@sonicjs-cms/core'

// Re-run migrations
await runMigrations(db)

// Re-sync collections
await collectionSync.syncAll()

First Admin User

Issue: Cannot log in, no admin user exists

Solutions:

Create Admin User

# Set initial admin via environment
# wrangler.toml or secrets
ADMIN_EMAIL=[email protected]
ADMIN_PASSWORD=your-secure-password

Or create via API (if registration is enabled):

Create Admin via API

curl -X POST https://your-app.workers.dev/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "your-secure-password",
    "username": "admin"
  }'

Debug Tools

Logging Service

SonicJS includes a comprehensive logging service:

Using the Logger

import { Logger } from '@sonicjs-cms/core'

const logger = new Logger(db, {
  level: 'debug',  // debug, info, warn, error, fatal
  category: 'my-feature'
})

// Log with context
logger.debug('Processing request', { userId, action })
logger.info('Operation completed', { duration: Date.now() - start })
logger.error('Operation failed', { error: error.message })

View Logs

Query Logs

// Get recent logs
const logs = await db
  .prepare(`
    SELECT * FROM logs
    WHERE created_at > datetime('now', '-1 hour')
    ORDER BY created_at DESC
    LIMIT 100
  `)
  .all()

// Filter by category
const authLogs = await db
  .prepare(`
    SELECT * FROM logs
    WHERE category = 'auth'
    ORDER BY created_at DESC
  `)
  .all()

Debug Mode

Enable debug mode for verbose logging:

Enable Debug

# wrangler.toml
[env.development.vars]
ENVIRONMENT = "development"
DEBUG = "true"

Plugin Debugging

Each plugin gets a namespaced logger:

Plugin Logging

// In your plugin
builder.setLogger((msg, level) => {
  console.log(`[Plugin:my-plugin] [${level}] ${msg}`)
})

Error Reference

HTTP Status Codes

CodeMeaningCommon Causes
400Bad RequestValidation failed, missing fields, invalid JSON
401UnauthorizedNo token, invalid token, expired token
403ForbiddenInsufficient role/permissions
404Not FoundResource doesn't exist
409ConflictDuplicate slug, unique constraint violation
500Server ErrorUnhandled exception, database error

Error Response Format

All API errors return a consistent format:

Error Response

{
  "error": "Human-readable error message",
  "details": "Technical details (in development)",
  "code": "ERROR_CODE"
}

Common Error Codes

CodeMessageSolution
AUTH_REQUIREDAuthentication requiredAdd valid JWT token
AUTH_EXPIREDToken expiredRefresh or re-login
AUTH_INVALIDInvalid credentialsCheck email/password
PERM_DENIEDInsufficient permissionsCheck user role
NOT_FOUNDResource not foundVerify ID/slug
DUPLICATEAlready existsUse unique value
VALIDATIONValidation failedCheck required fields

Getting Help

If you're still stuck:

  1. Check GitHub Issues: Search for similar problems at github.com/lane711/sonicjs/issues
  2. Join Discord: Get help from the community
  3. Open an Issue: Report bugs with reproduction steps

Was this page helpful?