bknd-troubleshoot

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Troubleshoot Common Errors

常见错误排查指南

Quick-reference guide for resolving Bknd errors by error code, symptom, or common mistake pattern.
这是一份通过错误代码、症状或常见错误模式解决Bknd错误的速查指南。

Prerequisites

前置条件

  • Bknd project running (or attempting to run)
  • Error message or symptom to diagnose
  • Bknd项目正在运行(或尝试启动)
  • 有待诊断的错误信息或症状

Error Code Quick Reference

错误代码速查

400 Bad Request

400 Bad Request

Cause: Invalid request body or parameters
Quick fixes:
bash
undefined
原因: 请求体或参数无效
快速修复方案:
bash
undefined

Check JSON validity

检查JSON有效性

echo '{"title":"Test"}' | jq .
echo '{"title":"Test"}' | jq .

Verify Content-Type header

验证Content-Type请求头

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
curl -X POST http://localhost:3000/api/data/posts
-H "Content-Type: application/json"
-d '{"title":"Test"}'

**常见诱因:**
- 缺少`Content-Type: application/json`请求头
- JSON体格式错误
- 缺少必填字段
- 字段类型无效(应为数字却传入字符串)
- 枚举值无效

401 Unauthorized

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
});
原因: 缺少或无效的身份验证信息
快速修复方案:
typescript
// 检查token是否存在
console.log(localStorage.getItem("bknd_token"));

// 通过/me端点验证token
const me = await api.auth.me();
console.log(me.ok ? "有效" : "无效/已过期");
常见诱因:
  • 未存储token(Api配置中缺少
    storage: localStorage
  • Token已过期(检查JWT的
    expires
    配置)
  • 身份验证请求头格式错误(必须为
    Bearer <token>
  • 未发送Cookie(缺少
    credentials: "include"
修复模板:
typescript
const api = new Api({
  host: "http://localhost:3000",
  storage: localStorage,  // 用于持久化token的必填配置
});

403 Forbidden

403 Forbidden

Cause: Authenticated but insufficient permissions
Quick fixes:
bash
undefined
原因: 已通过身份验证,但权限不足
快速修复方案:
bash
undefined

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
        ]
      }
    }
  }
}
curl http://localhost:3000/api/auth/me
-H "Authorization: Bearer <token>"

**常见诱因:**
- 配置中未启用Guard
- 角色缺少必要权限
- 需要实体特定权限
- 行级策略阻止了访问

**修复模板:**
```typescript
auth: {
  guard: {
    enabled: true,
    roles: {
      user: {
        permissions: [
          "data.entity.read",
          "data.entity.create",  // 添加缺失的权限
        ]
      }
    }
  }
}

404 Not Found

404 Not Found

Cause: Endpoint or record doesn't exist
Quick fixes:
bash
undefined
原因: 端点或记录不存在
快速修复方案:
bash
undefined

List available routes

列出所有可用路由

npx bknd debug routes
npx bknd debug routes

List entities

列出所有实体

Check entity name case (must match exactly)

检查实体名称大小写(必须完全匹配)


**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

**常见诱因:**
- 实体名称大小写不匹配(`Posts` vs `posts`)
- 未同步Schema(重启服务器)
- 端点路径错误(`/api/auth/login` vs `/api/auth/password/login`)
- 记录ID不存在

409 Conflict

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
原因: 值重复或违反约束条件
快速修复方案:
typescript
// 创建前检查记录是否已存在
const exists = await api.data.readOneBy("users", { email });
if (!exists.ok) {
  await api.data.createOne("users", { email, ... });
}
常见诱因:
  • 唯一字段值重复
  • 用户邮箱已注册
  • 字段设置了唯一约束

413 Payload Too Large

413 Payload Too Large

Cause: File upload exceeds size limit
Fix:
typescript
media: {
  body_max_size: 50 * 1024 * 1024,  // 50MB
}
原因: 文件上传超出大小限制
修复方案:
typescript
media: {
  body_max_size: 50 * 1024 * 1024,  // 50MB
}

500 Internal Server Error

500 Internal Server Error

Cause: Unhandled server exception
Quick fixes:
bash
undefined
原因: 服务器未处理的异常
快速修复方案:
bash
undefined

Check server logs for stack trace

检查服务器日志中的堆栈跟踪

Look for error details in response body

在响应体中查找错误详情


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

**常见诱因:**
- 数据库连接失败
- Schema配置无效
- 种子数据/插件中存在未处理的异常
- 缺少环境变量

Common Mistake Patterns

常见错误模式

Using em() as EntityManager

将em()用作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");
错误写法:
typescript
const schema = em({
  posts: entity("posts", { title: text() }),
});
schema.repo("posts").find();  // 报错!
正确写法:
typescript
// em()仅用于Schema定义
const schema = em({
  posts: entity("posts", { title: text() }),
});

// 使用SDK执行查询
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
错误写法:
bash
POST /api/auth/login        # 404
POST /api/auth/register     # 404
正确写法:
bash
POST /api/auth/password/login      # 密码验证策略
POST /api/auth/password/register
POST /api/auth/google/login        # Google OAuth策略

Missing Storage in Api Config

Api配置中缺少Storage

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
});
症状: Token无法持久化,刷新后自动登出
错误写法:
typescript
const api = new Api({
  host: "http://localhost:3000",
});
正确写法:
typescript
const api = new Api({
  host: "http://localhost:3000",
  storage: localStorage,  // 或sessionStorage
});

Using enum() Instead of enumm()

使用enum()而非enumm()

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

entity("posts", {
  status: enumm(["draft", "published"]),
});
错误写法:
typescript
import { enum } from "bknd";  // 语法错误 - 关键字
正确写法:
typescript
import { enumm } from "bknd";

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

Using primary() Function

使用primary()函数

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" });
错误写法:
typescript
import { primary } from "bknd";  // v0.20.0中已不再导出
正确写法:
typescript
// 主键会自动生成
// 如需自定义格式:
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
}]
错误写法:
typescript
permissions: [{
  permission: "data.entity.read",
  filter: { user_id: { $eq: "@user.id" } },  // 前缀错误
}]
正确写法:
typescript
permissions: [{
  permission: "data.entity.read",
  filter: { user_id: { $eq: "@auth.user.id" } },  // 正确前缀
}]

Memory Database for Persistent Data

用内存数据库存储持久化数据

Symptom: Data disappears on restart
Wrong:
bash
npx bknd run --memory
症状: 重启后数据消失
错误写法:
bash
npx bknd run --memory

Or config: { url: ":memory:" }

或配置:{ url: ":memory:" }


**Correct:**
```bash
npx bknd run --db-url "file:data.db"

**正确写法:**
```bash
npx bknd run --db-url "file:data.db"

Or config: { url: "file:data.db" }

或配置:{ url: "file:data.db" }

undefined
undefined

Missing Guard Enable

未启用Guard

Symptom: Permissions not working, everyone has access
Wrong:
typescript
auth: {
  guard: {
    roles: { ... }  // Guard not enabled!
  }
}
Correct:
typescript
auth: {
  guard: {
    enabled: true,  // Required!
    roles: { ... }
  }
}
症状: 权限配置不生效,所有用户都可访问
错误写法:
typescript
auth: {
  guard: {
    roles: { ... }  // 未启用Guard!
  }
}
正确写法:
typescript
auth: {
  guard: {
    enabled: true,  // 必填!
    roles: { ... }
  }
}

CORS Cookie Issues

CORS Cookie问题

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" });
症状: 在Postman中身份验证正常,但浏览器中失效
修复方案:
typescript
// 服务器配置
server: {
  cors: {
    origin: ["http://localhost:5173"],
    credentials: true,
  }
}

auth: {
  cookie: {
    secure: false,     // 开发环境HTTP下设为false
    sameSite: "lax",   // OAuth场景下不要设为"strict"
  }
}

// 客户端请求
fetch(url, { credentials: "include" });

Filter vs Allow/Deny Effect

Filter与Allow/Deny的作用差异

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" } },
}]
症状: 行级安全(RLS)过滤器返回所有记录,未生效
错误写法:
typescript
permissions: [{
  permission: "data.entity.read",
  effect: "allow",  // 不会过滤结果!
  condition: { user_id: { $eq: "@auth.user.id" } },
}]
正确写法:
typescript
permissions: [{
  permission: "data.entity.read",
  effect: "filter",  // 会过滤结果
  filter: { user_id: { $eq: "@auth.user.id" } },
}]

Quick Diagnostic Commands

快速诊断命令

Check Server Health

检查服务器健康状态

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

List All Routes

列出所有路由

bash
npx bknd debug routes
bash
npx bknd debug routes

Check Config Paths

检查配置路径

bash
npx bknd debug paths
bash
npx bknd debug paths

Test Auth

测试身份验证

bash
undefined
bash
undefined

Login

登录

curl -X POST http://localhost:3000/api/auth/password/login
-H "Content-Type: application/json"
-d '{"email":"test@example.com","password":"password"}'
curl -X POST http://localhost:3000/api/auth/password/login
-H "Content-Type: application/json"
-d '{"email":"test@example.com","password":"password"}'

Check token

验证token

curl http://localhost:3000/api/auth/me
-H "Authorization: Bearer <token>"
undefined
curl http://localhost:3000/api/auth/me
-H "Authorization: Bearer <token>"
undefined

Test Entity Access

测试实体访问权限

bash
undefined
bash
undefined

Unauthenticated

未认证状态

Authenticated

已认证状态

curl http://localhost:3000/api/data/posts
-H "Authorization: Bearer <token>"
undefined
curl http://localhost:3000/api/data/posts
-H "Authorization: Bearer <token>"
undefined

Check Schema

检查Schema

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

Environment-Specific Issues

环境特定问题

Development

开发环境

IssueSolution
Config not loadingCheck file name:
bknd.config.ts
Port in use
npx bknd run --port 3001
Types outdated
npx bknd types
Hot reload not workingRestart server
问题解决方案
配置未加载检查文件名:
bknd.config.ts
端口被占用
npx bknd run --port 3001
类型定义过时
npx bknd types
热重载失效重启服务器

Production

生产环境

IssueSolution
JWT errorsSet
JWT_SECRET
env var (32+ chars)
Cookie not set
secure: true
for HTTPS
500 errorsCheck logs, set
NODE_ENV=production
D1 not foundCheck wrangler.json bindings
问题解决方案
JWT错误设置
JWT_SECRET
环境变量(长度≥32字符)
Cookie未设置HTTPS环境下设
secure: true
500错误检查日志,设置
NODE_ENV=production
D1未找到检查wrangler.json绑定配置

Serverless

无服务器环境

IssueSolution
Cold start slowUse edge-compatible DB (D1, Turso)
File upload failsUse S3/R2, not local storage
SQLite native errorUse LibSQL or PostgreSQL
问题解决方案
冷启动缓慢使用边缘兼容数据库(D1、Turso)
文件上传失败使用S3/R2,不要用本地存储
SQLite原生错误使用LibSQL或PostgreSQL

Symptom-Based Troubleshooting

基于症状的排查

"Config file could not be resolved"

"Config file could not be resolved"

bash
undefined
bash
undefined

Check file exists

检查文件是否存在

ls bknd.config.*
ls bknd.config.*

Specify explicitly

显式指定配置文件

npx bknd run -c ./bknd.config.ts
undefined
npx bknd run -c ./bknd.config.ts
undefined

"EADDRINUSE: address already in use"

"EADDRINUSE: address already in use"

bash
undefined
bash
undefined

Find process

查找占用进程

lsof -i :3000
lsof -i :3000

Use different port

使用其他端口

npx bknd run --port 3001
undefined
npx bknd run --port 3001
undefined

"spawn xdg-open ENOENT"

"spawn xdg-open ENOENT"

bash
undefined
bash
undefined

Headless server - disable browser open

无头服务器环境 - 禁止自动打开浏览器

npx bknd run --no-open
undefined
npx bknd run --no-open
undefined

"Data disappears after restart"

"Data disappears after restart"

bash
undefined
bash
undefined

Check for memory mode in output

检查输出中是否有内存模式标识

Use file database

使用文件数据库

npx bknd run --db-url "file:data.db"
undefined
npx bknd run --db-url "file:data.db"
undefined

"ERR_UNSUPPORTED_ESM_URL_SCHEME" (Windows)

"ERR_UNSUPPORTED_ESM_URL_SCHEME"(Windows系统)

  1. Use Node.js 18+
  2. Add
    "type": "module"
    to package.json
  3. Use
    .mjs
    extension for config
  1. 使用Node.js 18及以上版本
  2. 在package.json中添加
    "type": "module"
  3. 配置文件使用
    .mjs
    扩展名

"TypeError: X is not a function"

"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
检查导入路径:
typescript
// SDK客户端
import { Api } from "bknd/client";

// Schema构建工具
import { em, entity, text } from "bknd";

// 适配器
import { serve } from "bknd/adapter/node";      // Node环境
import { serve } from "bknd/adapter/cloudflare"; // Cloudflare 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
    )
建议:
  • 优先检查服务器日志
  • 确保实体名称为小写
  • 调试前端前先用curl测试
  • 修改Schema后重启服务器
  • 遇到404错误时使用
    npx bknd debug routes
禁止:
  • em()
    用于运行时查询
  • :memory:
    存储持久化数据
  • 忘记在Api配置中添加
    storage: localStorage
  • 省略Guard的
    enabled: true
    配置
  • 使用
    @user.id
    (应使用
    @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
  • bknd-debugging - 全面调试指南
  • bknd-local-setup - 项目初始搭建
  • bknd-setup-auth - 身份验证配置
  • bknd-assign-permissions - 权限配置
  • bknd-api-discovery - 探索可用端点