| 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
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
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
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:
ls bknd.config.*
pwd
npx bknd debug paths
Solutions:
mv bknd.config.js bknd.config.ts
npx bknd run -c ./bknd.config.ts
Database Not Persisting
Symptoms: Data disappears on server restart
Diagnose:
npx bknd run
ls *.db
Solutions:
npx bknd run --db-url "file:data.db"
npx bknd run --memory
Port Already in Use
Symptoms: EADDRINUSE: address already in use
Diagnose:
lsof -i :3000
netstat -ano | findstr :3000
Solutions:
npx bknd run --port 3001
kill -9 <PID>
taskkill /PID <PID> /F
Authentication Not Working
Symptoms: 401 errors, token not persisting, user always null
Diagnose:
curl -X POST http://localhost:3000/api/auth/password/login \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","password":"password"}'
Solutions:
- Auth not enabled:
export default {
app: {
auth: { enabled: true },
}
}
- Wrong strategy path:
POST /api/auth/password/login
POST /api/auth/login
- JWT secret not set (production):
auth: {
jwt: {
secret: process.env.JWT_SECRET,
}
}
- Cookie not set (CORS):
auth: {
cookie: {
secure: false,
sameSite: "lax",
}
}
- Token not persisting (frontend):
const api = new Api({
host: "http://localhost:3000",
storage: localStorage,
});
Permission Denied (403)
Symptoms: Valid token but 403 Forbidden
Diagnose:
curl http://localhost:3000/api/auth/me \
-H "Authorization: Bearer <token>"
Solutions:
- Guard not enabled:
export default {
app: {
auth: {
guard: { enabled: true },
}
}
}
- No default role (anonymous access):
auth: {
guard: {
roles: {
anonymous: {
is_default: true,
permissions: ["data.entity.read"],
}
}
}
}
- Role missing permission:
roles: {
user: {
permissions: [
"data.entity.read",
"data.entity.create",
]
}
}
- Entity-specific permission needed:
permissions: [
{ permission: "data.entity.read", entity: "posts" },
]
Entity/Record Not Found (404)
Symptoms: 404 on data endpoints
Diagnose:
curl http://localhost:3000/api/data
curl http://localhost:3000/api/data/Posts
curl http://localhost:3000/api/data/posts
npx bknd debug routes | grep data
Solutions:
- Schema not synced:
npx bknd run
- Entity name case mismatch:
entity("posts", { ... })
api.data.readMany("posts");
api.data.readMany("Posts");
- Record doesn't exist:
const result = await api.data.readOne("posts", 999);
if (!result.ok) {
console.log("Not found:", result.status);
}
Type Errors with em()
Symptoms: TypeScript errors using schema object
Problem: em() returns schema definition, NOT queryable EntityManager.
const schema = em({
posts: entity("posts", { title: text() }),
});
schema.repo("posts").find();
const api = new Api({ url: "http://localhost:3000" });
await api.data.readMany("posts");
For direct database access (server-side only):
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:
curl http://localhost:3000/api/system/schema
Solutions:
- Restart server - schema syncs on startup:
npx bknd run
- Force sync (may drop data):
options: {
sync: {
force: true,
}
}
- Check mode - Database Mode ignores code schema:
mode: "code"
mode: "hybrid"
File Upload Failing
Symptoms: 413 error, upload silently fails
Diagnose:
ls -la myfile.jpg
curl -X POST http://localhost:3000/api/media/upload \
-H "Authorization: Bearer <token>" \
-F "file=@myfile.jpg"
Solutions:
- File too large:
media: {
body_max_size: 10 * 1024 * 1024,
}
- Storage not configured:
media: {
adapter: {
type: "s3",
}
}
- Local storage (dev only):
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:
curl -I http://localhost:3000/api/data/posts \
-H "Origin: http://localhost:5173"
Solutions:
export default {
app: {
server: {
cors: {
origin: ["http://localhost:5173", "https://myapp.com"],
credentials: true,
}
}
}
}
For development (allow all):
server: {
cors: {
origin: "*",
}
}
Headless Environment Crash
Symptoms: spawn xdg-open ENOENT on server without display
Solution:
npx bknd run --no-open
Windows ESM Errors
Symptoms: ERR_UNSUPPORTED_ESM_URL_SCHEME on Windows
Solutions:
- Use Node.js 18+
- Ensure
"type": "module" in package.json
- Use
.mjs extension for config
TypeScript Types Not Updating
Symptoms: IDE shows old types, autocomplete wrong
Solutions:
npx bknd types
rm -rf node_modules/.cache
Debug Script Pattern
Create a debug helper for systematic troubleshooting:
import { Api } from "bknd/client";
async function debug() {
const api = new Api({ host: "http://localhost:3000" });
console.log("=== Health Check ===");
const entities = await fetch("http://localhost:3000/api/data");
console.log("Status:", entities.status);
console.log("Entities:", await entities.json());
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);
console.log("\n=== Schema Check ===");
const schema = await fetch("http://localhost:3000/api/system/schema");
console.log("Schema:", await schema.json());
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:
npx tsx debug.ts
Logging Patterns
Server-Side Logging
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
const api = new Api({
host: "http://localhost:3000",
verbose: true,
});
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
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:
{
"success": false,
"errors": [
{
"task": "fetchUser",
"error": "Failed to fetch user: 404 Not Found",
"timestamp": "2024-01-15T10:30:00Z"
}
]
}
Task Error Handling
import { Task, Condition } from "bknd/flows";
const flow = new Flow("myFlow", [
mainTask,
errorTask.connect(mainTask, Condition.error()),
]);
Verification Checklist
When debugging, check these in order:
-
Server running?
curl http://localhost:3000/api/data
-
Config loaded?
- Check startup logs for "Using config from"
-
Schema synced?
- Check admin panel or
/api/system/schema
-
Auth enabled? (if needed)
- Check
auth: { enabled: true } in config
-
Permissions set? (if 403)
- Check
guard: { enabled: true } and roles
-
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