home / skills / cameronapak / bknd-skills / bknd-debugging

bknd-debugging skill

/skills/bknd-debugging

This skill helps you diagnose and fix common Bknd issues by guiding CLI usage, error analysis, and logs for faster troubleshooting.

npx playbooks add skill cameronapak/bknd-skills --skill bknd-debugging

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
13.3 KB
---
name: bknd-debugging
description: Use when troubleshooting Bknd issues, debugging errors, fixing common problems, or diagnosing why something isn't working. Covers CLI debug commands, error codes, logging, common issues and solutions.
---

# Debugging Common Issues

Diagnose and fix common Bknd problems using CLI tools, error analysis, and systematic troubleshooting.

## Prerequisites

- Bknd project set up locally
- Terminal/command line access
- Basic understanding of HTTP status codes

## When to Use UI Mode

- Inspecting data in admin panel (`/admin`)
- Verifying entity schema visually
- Testing CRUD operations manually
- Checking user/role configurations

## When to Use Code Mode

- Running debug CLI commands
- Analyzing API response errors
- Checking route registration
- Inspecting configuration paths
- Reviewing server logs

## CLI Debug Commands

### Show All Registered Routes

```bash
npx bknd debug routes
```

Output shows every HTTP endpoint:
- API routes (`/api/data/*`, `/api/auth/*`, `/api/media/*`)
- Admin routes (`/admin/*`)
- Custom Flow HTTP triggers
- Plugin routes

Use when: endpoint returns 404, verifying custom routes registered.

### Show Internal Paths

```bash
npx bknd debug paths
```

Output:
```
[PATHS] {
  rootpath: '/path/to/bknd',
  distPath: '/path/to/dist',
  relativeDistPath: './dist',
  cwd: '/your/project',
  dir: '/path/to/cli',
  resolvedPkg: '/path/to/package.json'
}
```

Use when: config file not loading, path resolution issues.

### CLI Help

```bash
npx bknd --help
npx bknd run --help
npx bknd types --help
```

## HTTP Error Codes

| Code | Meaning | Common Causes |
|------|---------|---------------|
| 400 | Bad Request | Invalid JSON, missing required fields, validation error |
| 401 | Unauthorized | Missing/invalid/expired token |
| 403 | Forbidden | Valid token but insufficient permissions |
| 404 | Not Found | Wrong endpoint, entity doesn't exist, record not found |
| 409 | Conflict | Duplicate unique field, user already exists |
| 413 | Payload Too Large | File upload exceeds `body_max_size` |
| 500 | Server Error | Unhandled exception, database error |

## Common Issues & Solutions

### Config File Not Loading

**Symptoms:** "Config file could not be resolved" error

**Diagnose:**
```bash
# Check config exists
ls bknd.config.*

# Check current directory
pwd

# Check what bknd sees
npx bknd debug paths
```

**Solutions:**
```bash
# Ensure correct extension
mv bknd.config.js bknd.config.ts

# Specify explicitly
npx bknd run -c ./bknd.config.ts

# Check supported extensions: .ts, .js, .mjs, .cjs, .json
```

### Database Not Persisting

**Symptoms:** Data disappears on server restart

**Diagnose:**
```bash
# Check if using memory mode
# Look for "Using in-memory" in startup output
npx bknd run

# Check for database file
ls *.db
```

**Solutions:**
```bash
# Use file-based database
npx bknd run --db-url "file:data.db"

# NOT memory mode
npx bknd run --memory  # Data will be lost!

# Verify in config:
# connection: { url: "file:data.db" }  ✓
# connection: { url: ":memory:" }      ✗
```

### Port Already in Use

**Symptoms:** `EADDRINUSE: address already in use`

**Diagnose:**
```bash
# Find process using port
lsof -i :3000

# Or on Windows
netstat -ano | findstr :3000
```

**Solutions:**
```bash
# Use different port
npx bknd run --port 3001

# Kill existing process
kill -9 <PID>

# Or on Windows
taskkill /PID <PID> /F
```

### Authentication Not Working

**Symptoms:** 401 errors, token not persisting, user always null

**Diagnose:**
```bash
# Test login endpoint
curl -X POST http://localhost:3000/api/auth/password/login \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","password":"password"}'

# Check auth configuration
# Look for "strategy" in response errors
```

**Solutions:**

1. **Auth not enabled:**
```typescript
export default {
  app: {
    auth: { enabled: true },  // Required!
  }
}
```

2. **Wrong strategy path:**
```bash
# Password auth endpoint:
POST /api/auth/password/login    # ✓
POST /api/auth/login             # ✗ 404
```

3. **JWT secret not set (production):**
```typescript
auth: {
  jwt: {
    secret: process.env.JWT_SECRET,  // Required for production
  }
}
```

4. **Cookie not set (CORS):**
```typescript
auth: {
  cookie: {
    secure: false,     // Set true only for HTTPS
    sameSite: "lax",   // Not "strict" for OAuth
  }
}
```

5. **Token not persisting (frontend):**
```typescript
const api = new Api({
  host: "http://localhost:3000",
  storage: localStorage,  // Required for token persistence
});
```

### Permission Denied (403)

**Symptoms:** Valid token but 403 Forbidden

**Diagnose:**
```bash
# Check user's role
curl http://localhost:3000/api/auth/me \
  -H "Authorization: Bearer <token>"

# Check role permissions in config
```

**Solutions:**

1. **Guard not enabled:**
```typescript
export default {
  app: {
    auth: {
      guard: { enabled: true },  // Required for permissions
    }
  }
}
```

2. **No default role (anonymous access):**
```typescript
auth: {
  guard: {
    roles: {
      anonymous: {
        is_default: true,  // Allow unauthenticated access
        permissions: ["data.entity.read"],
      }
    }
  }
}
```

3. **Role missing permission:**
```typescript
roles: {
  user: {
    permissions: [
      "data.entity.read",
      "data.entity.create",  // Add if needed
    ]
  }
}
```

4. **Entity-specific permission needed:**
```typescript
permissions: [
  { permission: "data.entity.read", entity: "posts" },
]
```

### Entity/Record Not Found (404)

**Symptoms:** 404 on data endpoints

**Diagnose:**
```bash
# List all entities
curl http://localhost:3000/api/data

# Check entity name (case-sensitive)
curl http://localhost:3000/api/data/Posts    # ✗
curl http://localhost:3000/api/data/posts    # ✓

# Verify routes
npx bknd debug routes | grep data
```

**Solutions:**

1. **Schema not synced:**
```bash
# Restart server to sync schema
npx bknd run
```

2. **Entity name case mismatch:**
```typescript
// Schema defines lowercase
entity("posts", { ... })

// API call must match exactly
api.data.readMany("posts");     // ✓
api.data.readMany("Posts");     // ✗ 404
```

3. **Record doesn't exist:**
```typescript
const result = await api.data.readOne("posts", 999);
if (!result.ok) {
  console.log("Not found:", result.status);  // 404
}
```

### Type Errors with em()

**Symptoms:** TypeScript errors using schema object

**Problem:** `em()` returns schema definition, NOT queryable EntityManager.

```typescript
// WRONG - this will fail
const schema = em({
  posts: entity("posts", { title: text() }),
});
schema.repo("posts").find();  // ✗ Error!

// CORRECT - use SDK for queries
const api = new Api({ url: "http://localhost:3000" });
await api.data.readMany("posts");  // ✓
```

For direct database access (server-side only):
```typescript
const app = new App(config);
await app.build();
const posts = await app.em.repo("posts").findMany();  // ✓
```

### Schema Sync Issues

**Symptoms:** Entity exists in code but not in database, or vice versa

**Diagnose:**
```bash
# Check admin panel -> Schema view
# Or query directly
curl http://localhost:3000/api/system/schema
```

**Solutions:**

1. **Restart server** - schema syncs on startup:
```bash
npx bknd run
```

2. **Force sync** (may drop data):
```typescript
options: {
  sync: {
    force: true,  // Dangerous! Can drop tables
  }
}
```

3. **Check mode** - Database Mode ignores code schema:
```typescript
// Code Mode (default) - schema from code
mode: "code"

// Hybrid Mode - merges code + database
mode: "hybrid"
```

### File Upload Failing

**Symptoms:** 413 error, upload silently fails

**Diagnose:**
```bash
# Check file size
ls -la myfile.jpg

# Test upload
curl -X POST http://localhost:3000/api/media/upload \
  -H "Authorization: Bearer <token>" \
  -F "[email protected]"
```

**Solutions:**

1. **File too large:**
```typescript
media: {
  body_max_size: 10 * 1024 * 1024,  // 10MB
}
```

2. **Storage not configured:**
```typescript
media: {
  adapter: {
    type: "s3",
    // ... S3 config
  }
}
```

3. **Local storage (dev only):**
```typescript
import { registerLocalMediaAdapter } from "bknd/adapter/node";
const local = registerLocalMediaAdapter();

export default {
  app: {
    media: { adapter: local }
  }
}
```

### CORS Errors

**Symptoms:** "Access-Control-Allow-Origin" errors in browser console

**Diagnose:**
```bash
# Check CORS headers
curl -I http://localhost:3000/api/data/posts \
  -H "Origin: http://localhost:5173"
```

**Solutions:**
```typescript
export default {
  app: {
    server: {
      cors: {
        origin: ["http://localhost:5173", "https://myapp.com"],
        credentials: true,  // For cookies
      }
    }
  }
}
```

For development (allow all):
```typescript
server: {
  cors: {
    origin: "*",
  }
}
```

### Headless Environment Crash

**Symptoms:** `spawn xdg-open ENOENT` on server without display

**Solution:**
```bash
npx bknd run --no-open
```

### Windows ESM Errors

**Symptoms:** `ERR_UNSUPPORTED_ESM_URL_SCHEME` on Windows

**Solutions:**
1. Use Node.js 18+
2. Ensure `"type": "module"` in package.json
3. Use `.mjs` extension for config

### TypeScript Types Not Updating

**Symptoms:** IDE shows old types, autocomplete wrong

**Solutions:**
```bash
# Regenerate types
npx bknd types

# Restart TypeScript server (VS Code)
# Cmd/Ctrl + Shift + P -> "TypeScript: Restart TS Server"

# Clear cache
rm -rf node_modules/.cache
```

## Debug Script Pattern

Create a debug helper for systematic troubleshooting:

```typescript
// debug.ts
import { Api } from "bknd/client";

async function debug() {
  const api = new Api({ host: "http://localhost:3000" });

  // 1. Check server health
  console.log("=== Health Check ===");
  const entities = await fetch("http://localhost:3000/api/data");
  console.log("Status:", entities.status);
  console.log("Entities:", await entities.json());

  // 2. Check auth
  console.log("\n=== Auth Check ===");
  const me = await api.auth.me();
  console.log("Auth status:", me.ok ? "authenticated" : "not authenticated");
  if (me.data) console.log("User:", me.data);

  // 3. Check schema
  console.log("\n=== Schema Check ===");
  const schema = await fetch("http://localhost:3000/api/system/schema");
  console.log("Schema:", await schema.json());

  // 4. Test entity access
  console.log("\n=== Entity Access ===");
  const posts = await api.data.readMany("posts", { limit: 1 });
  console.log("Posts access:", posts.ok ? "success" : `failed (${posts.status})`);
}

debug().catch(console.error);
```

Run with:
```bash
npx tsx debug.ts
```

## Logging Patterns

### Server-Side Logging

```typescript
// In seed function or plugin
options: {
  seed: async (ctx) => {
    console.log("[SEED] Starting...");
    console.log("[SEED] Entities:", Object.keys(ctx.em.entities));

    try {
      await ctx.em.mutator("posts").insertOne({ title: "Test" });
      console.log("[SEED] Created post");
    } catch (e) {
      console.error("[SEED] Error:", e);
    }
  }
}
```

### API Response Logging

```typescript
const api = new Api({
  host: "http://localhost:3000",
  verbose: true,  // Logs all requests/responses
});

// Or manual logging
const result = await api.data.readMany("posts");
console.log("Request result:", {
  ok: result.ok,
  status: result.status,
  data: result.data,
  error: result.error,
});
```

### Custom Fetcher with Logging

```typescript
const api = new Api({
  host: "http://localhost:3000",
  fetcher: async (url, options) => {
    console.log("→", options?.method || "GET", url);
    const start = Date.now();
    const response = await fetch(url, options);
    console.log("←", response.status, `(${Date.now() - start}ms)`);
    return response;
  },
});
```

## Flow/Task Debugging

### HTTP Trigger Errors

Sync mode returns errors in response:
```json
{
  "success": false,
  "errors": [
    {
      "task": "fetchUser",
      "error": "Failed to fetch user: 404 Not Found",
      "timestamp": "2024-01-15T10:30:00Z"
    }
  ]
}
```

### Task Error Handling

```typescript
import { Task, Condition } from "bknd/flows";

const flow = new Flow("myFlow", [
  mainTask,
  errorTask.connect(mainTask, Condition.error()),  // Handle errors
]);
```

## Verification Checklist

When debugging, check these in order:

1. **Server running?**
   ```bash
   curl http://localhost:3000/api/data
   ```

2. **Config loaded?**
   - Check startup logs for "Using config from"

3. **Schema synced?**
   - Check admin panel or `/api/system/schema`

4. **Auth enabled?** (if needed)
   - Check `auth: { enabled: true }` in config

5. **Permissions set?** (if 403)
   - Check `guard: { enabled: true }` and roles

6. **CORS configured?** (if browser errors)
   - Check `server: { cors: {...} }`

## DOs and DON'Ts

**DO:**
- Check server logs first
- Use `npx bknd debug routes` for 404s
- Verify entity names match exactly (case-sensitive)
- Test with curl before debugging frontend
- Use `verbose: true` in Api for request logging
- Restart server after schema changes

**DON'T:**
- Assume `em()` returns a queryable EntityManager
- Forget `--no-open` on headless servers
- Use `:memory:` database for persistent data
- Skip checking HTTP status codes in responses
- Ignore CORS when debugging frontend issues
- Use `sync: { force: true }` in production

## Related Skills

- **bknd-local-setup** - Initial project setup
- **bknd-env-config** - Environment variables
- **bknd-setup-auth** - Authentication configuration
- **bknd-assign-permissions** - Permission troubleshooting
- **bknd-api-discovery** - Explore available endpoints

Overview

This skill helps you diagnose and fix common Bknd issues quickly using CLI tools, logs, and targeted checks. It covers route and path inspection, HTTP error analysis, auth and permission fixes, schema sync, file uploads, CORS, and environment pitfalls. Use it to shorten time-to-resolution and avoid destructive changes in production.

How this skill works

The skill guides you through systematic checks: verify server health, inspect registered routes and internal paths, run debug CLI commands, and examine API responses and logs. It explains common HTTP status causes and maps them to concrete CLI commands or config fixes. Practical examples include auth troubleshooting, database persistence checks, and a reusable debug script pattern to automate basic validation.

When to use it

  • Endpoint returns 404 or route registration seems missing
  • Authentication fails with 401/403 or tokens don’t persist
  • Data disappears after restart or database behaves like in-memory
  • File uploads fail with 413 or storage misconfiguration
  • Browser shows CORS errors or headless server crashes

Best practices

  • Start with simple curl checks to confirm server and endpoints before debugging frontend
  • Use npx bknd debug routes and npx bknd debug paths to verify routes and config resolution
  • Enable verbose logging in the Api client and add custom fetcher logs for request/response timing
  • Avoid sync: { force: true } in production; restart the server to apply schema changes
  • Use file-based DB for persistence; don’t use :memory: when you need durable data

Example use cases

  • Fix 404 by confirming route registration and exact case-sensitive entity name
  • Resolve 401 by enabling auth in config, ensuring JWT secret in production, and confirming cookie/CORS settings
  • Recover persistent storage by switching from memory mode to a file URL and verifying .db file presence
  • Diagnose upload failures by checking file size, media adapter config, and body_max_size
  • Automate a quick health/auth/schema check with the provided debug.ts script

FAQ

What CLI commands reveal registered routes and internal paths?

Use npx bknd debug routes to list endpoints and npx bknd debug paths to see resolved internal paths and cwd.

Why does data disappear after restarting the server?

The server is running in memory mode. Switch to a file-based DB (npx bknd run --db-url "file:data.db") and verify the .db file exists.