home / skills / cameronapak / bknd-skills / bknd-troubleshoot

bknd-troubleshoot skill

/skills/bknd-troubleshoot

This skill helps you diagnose and fix bknd errors quickly by error code, symptom, or common pattern.

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

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

Files (1)
SKILL.md
10.0 KB
---
name: bknd-troubleshoot
description: Use when encountering Bknd errors, getting error messages, something not working, or needing quick fixes. Covers error code reference, quick solutions, and common mistake patterns.
---

# Troubleshoot Common Errors

Quick-reference guide for resolving Bknd errors by error code, symptom, or common mistake pattern.

## Prerequisites

- Bknd project running (or attempting to run)
- Error message or symptom to diagnose

## Error Code Quick Reference

### 400 Bad Request

**Cause:** Invalid request body or parameters

**Quick fixes:**
```bash
# Check JSON validity
echo '{"title":"Test"}' | jq .

# Verify Content-Type header
curl -X POST http://localhost:3000/api/data/posts \
  -H "Content-Type: application/json" \
  -d '{"title":"Test"}'
```

**Common causes:**
- Missing `Content-Type: application/json` header
- Malformed JSON body
- Missing required field
- Invalid field type (string instead of number)
- Invalid enum value

### 401 Unauthorized

**Cause:** Missing or invalid authentication

**Quick fixes:**
```typescript
// Check token exists
console.log(localStorage.getItem("bknd_token"));

// Verify token with /me endpoint
const me = await api.auth.me();
console.log(me.ok ? "Valid" : "Invalid/expired");
```

**Common causes:**
- Token not stored (missing `storage: localStorage` in Api config)
- Token expired (check JWT `expires` config)
- Wrong auth header format (must be `Bearer <token>`)
- Cookie not sent (missing `credentials: "include"`)

**Fix pattern:**
```typescript
const api = new Api({
  host: "http://localhost:3000",
  storage: localStorage,  // Required for token persistence
});
```

### 403 Forbidden

**Cause:** Authenticated but insufficient permissions

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

**Common causes:**
- Guard not enabled in config
- Role missing required permission
- Entity-specific permission needed
- Row-level policy blocking access

**Fix pattern:**
```typescript
auth: {
  guard: {
    enabled: true,
    roles: {
      user: {
        permissions: [
          "data.entity.read",
          "data.entity.create",  // Add missing permission
        ]
      }
    }
  }
}
```

### 404 Not Found

**Cause:** Endpoint or record doesn't exist

**Quick fixes:**
```bash
# List available routes
npx bknd debug routes

# List entities
curl http://localhost:3000/api/data

# Check entity name case (must match exactly)
curl http://localhost:3000/api/data/posts    # lowercase
```

**Common causes:**
- Entity name case mismatch (`Posts` vs `posts`)
- Schema not synced (restart server)
- Wrong endpoint path (`/api/auth/login` vs `/api/auth/password/login`)
- Record ID doesn't exist

### 409 Conflict

**Cause:** Duplicate value or constraint violation

**Quick fixes:**
```typescript
// Check for existing record before create
const exists = await api.data.readOneBy("users", { email });
if (!exists.ok) {
  await api.data.createOne("users", { email, ... });
}
```

**Common causes:**
- Duplicate unique field value
- User email already registered
- Unique constraint on field

### 413 Payload Too Large

**Cause:** File upload exceeds size limit

**Fix:**
```typescript
media: {
  body_max_size: 50 * 1024 * 1024,  // 50MB
}
```

### 500 Internal Server Error

**Cause:** Unhandled server exception

**Quick fixes:**
```bash
# Check server logs for stack trace
# Look for error details in response body
curl http://localhost:3000/api/data/posts 2>&1 | jq .error
```

**Common causes:**
- Database connection failed
- Invalid schema configuration
- Unhandled exception in seed/plugin
- Missing environment variable

## Common Mistake Patterns

### Using em() as EntityManager

**Wrong:**
```typescript
const schema = em({
  posts: entity("posts", { title: text() }),
});
schema.repo("posts").find();  // Error!
```

**Correct:**
```typescript
// em() is for schema definition only
const schema = em({
  posts: entity("posts", { title: text() }),
});

// Use SDK for queries
const api = new Api({ host: "http://localhost:3000" });
await api.data.readMany("posts");
```

### Wrong Auth Endpoint Path

**Wrong:**
```bash
POST /api/auth/login        # 404
POST /api/auth/register     # 404
```

**Correct:**
```bash
POST /api/auth/password/login      # For password strategy
POST /api/auth/password/register
POST /api/auth/google/login        # For Google OAuth
```

### Missing Storage in Api Config

**Symptom:** Token not persisting, logged out after refresh

**Wrong:**
```typescript
const api = new Api({
  host: "http://localhost:3000",
});
```

**Correct:**
```typescript
const api = new Api({
  host: "http://localhost:3000",
  storage: localStorage,  // Or sessionStorage
});
```

### Using enum() Instead of enumm()

**Wrong:**
```typescript
import { enum } from "bknd";  // Syntax error - reserved word
```

**Correct:**
```typescript
import { enumm } from "bknd";

entity("posts", {
  status: enumm(["draft", "published"]),
});
```

### Using primary() Function

**Wrong:**
```typescript
import { primary } from "bknd";  // Not exported in v0.20.0
```

**Correct:**
```typescript
// Primary keys are auto-generated
// To customize format:
entity("posts", { title: text() }, { primary_format: "uuid" });
```

### Wrong Policy Variable Prefix

**Wrong:**
```typescript
permissions: [{
  permission: "data.entity.read",
  filter: { user_id: { $eq: "@user.id" } },  // Wrong prefix
}]
```

**Correct:**
```typescript
permissions: [{
  permission: "data.entity.read",
  filter: { user_id: { $eq: "@auth.user.id" } },  // Correct prefix
}]
```

### Memory Database for Persistent Data

**Symptom:** Data disappears on restart

**Wrong:**
```bash
npx bknd run --memory
# Or config: { url: ":memory:" }
```

**Correct:**
```bash
npx bknd run --db-url "file:data.db"
# Or config: { url: "file:data.db" }
```

### Missing Guard Enable

**Symptom:** Permissions not working, everyone has access

**Wrong:**
```typescript
auth: {
  guard: {
    roles: { ... }  // Guard not enabled!
  }
}
```

**Correct:**
```typescript
auth: {
  guard: {
    enabled: true,  // Required!
    roles: { ... }
  }
}
```

### CORS Cookie Issues

**Symptom:** Auth works in Postman but not browser

**Fix:**
```typescript
// Server config
server: {
  cors: {
    origin: ["http://localhost:5173"],
    credentials: true,
  }
}

auth: {
  cookie: {
    secure: false,     // false for HTTP dev
    sameSite: "lax",   // Not "strict" for OAuth
  }
}

// Client fetch
fetch(url, { credentials: "include" });
```

### Filter vs Allow/Deny Effect

**Symptom:** RLS filter returns all records instead of filtering

**Wrong:**
```typescript
permissions: [{
  permission: "data.entity.read",
  effect: "allow",  // Won't filter!
  condition: { user_id: { $eq: "@auth.user.id" } },
}]
```

**Correct:**
```typescript
permissions: [{
  permission: "data.entity.read",
  effect: "filter",  // Filters results
  filter: { user_id: { $eq: "@auth.user.id" } },
}]
```

## Quick Diagnostic Commands

### Check Server Health

```bash
curl http://localhost:3000/api/data
```

### List All Routes

```bash
npx bknd debug routes
```

### Check Config Paths

```bash
npx bknd debug paths
```

### Test Auth

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

# Check token
curl http://localhost:3000/api/auth/me \
  -H "Authorization: Bearer <token>"
```

### Test Entity Access

```bash
# Unauthenticated
curl http://localhost:3000/api/data/posts

# Authenticated
curl http://localhost:3000/api/data/posts \
  -H "Authorization: Bearer <token>"
```

### Check Schema

```bash
curl http://localhost:3000/api/system/schema
```

## Environment-Specific Issues

### Development

| Issue | Solution |
|-------|----------|
| Config not loading | Check file name: `bknd.config.ts` |
| Port in use | `npx bknd run --port 3001` |
| Types outdated | `npx bknd types` |
| Hot reload not working | Restart server |

### Production

| Issue | Solution |
|-------|----------|
| JWT errors | Set `JWT_SECRET` env var (32+ chars) |
| Cookie not set | `secure: true` for HTTPS |
| 500 errors | Check logs, set `NODE_ENV=production` |
| D1 not found | Check wrangler.json bindings |

### Serverless

| Issue | Solution |
|-------|----------|
| Cold start slow | Use edge-compatible DB (D1, Turso) |
| File upload fails | Use S3/R2, not local storage |
| SQLite native error | Use LibSQL or PostgreSQL |

## Symptom-Based Troubleshooting

### "Config file could not be resolved"

```bash
# Check file exists
ls bknd.config.*

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

### "EADDRINUSE: address already in use"

```bash
# Find process
lsof -i :3000

# Use different port
npx bknd run --port 3001
```

### "spawn xdg-open ENOENT"

```bash
# Headless server - disable browser open
npx bknd run --no-open
```

### "Data disappears after restart"

```bash
# Check for memory mode in output
# Use file database
npx bknd run --db-url "file:data.db"
```

### "ERR_UNSUPPORTED_ESM_URL_SCHEME" (Windows)

1. Use Node.js 18+
2. Add `"type": "module"` to package.json
3. Use `.mjs` extension for config

### "TypeError: X is not a function"

Check import paths:
```typescript
// SDK client
import { Api } from "bknd/client";

// Schema builders
import { em, entity, text } from "bknd";

// Adapters
import { serve } from "bknd/adapter/node";      // Node
import { serve } from "bknd/adapter/cloudflare"; // CF Workers
```

## DOs and DON'Ts

**DO:**
- Check server logs first
- Verify entity names are lowercase
- Test with curl before debugging frontend
- Restart server after schema changes
- Use `npx bknd debug routes` for 404s

**DON'T:**
- Use `em()` for runtime queries
- Use `:memory:` for persistent data
- Forget `storage: localStorage` in Api
- Skip `enabled: true` for guard
- Use `@user.id` (use `@auth.user.id`)

## Related Skills

- **bknd-debugging** - Comprehensive debugging guide
- **bknd-local-setup** - Initial project setup
- **bknd-setup-auth** - Authentication configuration
- **bknd-assign-permissions** - Permission configuration
- **bknd-api-discovery** - Explore available endpoints

Overview

This skill helps diagnose and fix common Bknd.io errors quickly. It organizes troubleshooting by error code, symptom, and frequent mistake patterns to get projects back online fast. Use it for quick reference, actionable fixes, and configuration checks when something in your Bknd project fails.

How this skill works

The skill inspects error messages, HTTP status codes, server logs, and common misconfigurations to recommend targeted fixes. It maps symptoms (like auth failures, 404s, or disappearing data) to concise commands, code snippets, and config changes you can apply immediately. It also provides diagnostic commands to verify server health, routes, schema, and auth state.

When to use it

  • You see HTTP errors (400, 401, 403, 404, 409, 413, 500) from the Bknd API.
  • Authentication or permission checks fail in browser or API clients.
  • Data disappears after restart or uploads fail due to size/settings.
  • You get configuration or runtime errors during development or deploy.
  • You need fast, step-by-step fixes for common Bknd mistakes.

Best practices

  • Check server logs first and reproduce with curl before debugging frontend.
  • Keep entity names lowercase and restart server after schema changes.
  • Persist tokens with storage (localStorage/sessionStorage) in Api config.
  • Enable auth guard explicitly (enabled: true) when defining roles and permissions.
  • Use file-based DB in production; avoid :memory: for persistent data.

Example use cases

  • Fix 401 Unauthorized by verifying token storage, header format, or /me endpoint.
  • Resolve 404 by listing routes, checking entity case, or re-syncing schema.
  • Handle 409 duplicate errors by checking unique constraints before creating records.
  • Stop data loss by switching from memory DB to file DB and updating run command.
  • Troubleshoot CORS cookie issues by enabling credentials and correct sameSite/secure settings.

FAQ

What should I check first when I see a 500 error?

Check server logs and the response body for stack traces, verify DB connection and required environment variables, and inspect recent seed/plugin or schema changes.

Why am I authenticated in Postman but not in the browser?

Likely a cookie/CORS issue: enable credentials on the server, set cookie secure/sameSite appropriately for dev vs production, and use fetch with credentials: 'include'.