名称:bknd-错误排查 描述:当遇到Bknd错误、收到错误消息、某些功能不工作或需要快速修复时使用。涵盖错误代码参考、快速解决方案和常见错误模式。
排查常见错误
快速参考指南,通过错误代码、症状或常见错误模式解决Bknd错误。
先决条件
- Bknd项目正在运行(或尝试运行)
- 错误消息或症状用于诊断
错误代码快速参考
400 Bad Request
原因: 无效的请求体或参数
快速修复:
# 检查JSON有效性
echo '{"title":"Test"}' | jq .
# 验证Content-Type头
curl -X POST http://localhost:3000/api/data/posts \
-H "Content-Type: application/json" \
-d '{"title":"Test"}'
常见原因:
- 缺少
Content-Type: application/json头 - 格式错误的JSON体
- 缺少必需字段
- 无效字段类型(字符串代替数字)
- 无效枚举值
401 Unauthorized
原因: 缺少或无效的身份验证
快速修复:
// 检查令牌是否存在
console.log(localStorage.getItem("bknd_token"));
// 通过 /me 端点验证令牌
const me = await api.auth.me();
console.log(me.ok ? "有效" : "无效/过期");
常见原因:
- 令牌未存储(在Api配置中缺少
storage: localStorage) - 令牌过期(检查JWT
expires配置) - 错误的身份验证头格式(必须是
Bearer <token>) - Cookie未发送(缺少
credentials: "include")
修复模式:
const api = new Api({
host: "http://localhost:3000",
storage: localStorage, // 用于令牌持久化
});
403 Forbidden
原因: 已身份验证但权限不足
快速修复:
# 检查用户的角色
curl http://localhost:3000/api/auth/me \
-H "Authorization: Bearer <token>"
常见原因:
- 在配置中未启用防护
- 角色缺少必需权限
- 需要实体特定权限
- 行级策略阻止访问
修复模式:
auth: {
guard: {
enabled: true,
roles: {
user: {
permissions: [
"data.entity.read",
"data.entity.create", // 添加缺少的权限
]
}
}
}
}
404 Not Found
原因: 端点或记录不存在
快速修复:
# 列出可用路由
npx bknd debug routes
# 列出实体
curl http://localhost:3000/api/data
# 检查实体名称大小写(必须完全匹配)
curl http://localhost:3000/api/data/posts # 小写
常见原因:
- 实体名称大小写不匹配(
Posts与posts) - 模式未同步(重启服务器)
- 错误的端点路径(
/api/auth/login与/api/auth/password/login) - 记录ID不存在
409 Conflict
原因: 重复值或约束违规
快速修复:
// 在创建前检查现有记录
const exists = await api.data.readOneBy("users", { email });
if (!exists.ok) {
await api.data.createOne("users", { email, ... });
}
常见原因:
- 重复的唯一字段值
- 用户邮箱已注册
- 字段上的唯一约束
413 Payload Too Large
原因: 文件上传超过大小限制
修复:
media: {
body_max_size: 50 * 1024 * 1024, // 50MB
}
500 Internal Server Error
原因: 未处理的服务器异常
快速修复:
# 检查服务器日志以获取堆栈跟踪
# 在响应体中查找错误详情
curl http://localhost:3000/api/data/posts 2>&1 | jq .error
常见原因:
- 数据库连接失败
- 无效的模式配置
- 种子/插件中未处理的异常
- 缺少环境变量
常见错误模式
使用 em() 作为 EntityManager
错误:
const schema = em({
posts: entity("posts", { title: text() }),
});
schema.repo("posts").find(); // 错误!
正确:
// em() 仅用于模式定义
const schema = em({
posts: entity("posts", { title: text() }),
});
// 使用SDK进行查询
const api = new Api({ host: "http://localhost:3000" });
await api.data.readMany("posts");
错误的身份验证端点路径
错误:
POST /api/auth/login # 404
POST /api/auth/register # 404
正确:
POST /api/auth/password/login # 用于密码策略
POST /api/auth/password/register
POST /api/auth/google/login # 用于Google OAuth
在Api配置中缺少存储
症状: 令牌未持久化,刷新后登出
错误:
const api = new Api({
host: "http://localhost:3000",
});
正确:
const api = new Api({
host: "http://localhost:3000",
storage: localStorage, // 或 sessionStorage
});
使用 enum() 而不是 enumm()
错误:
import { enum } from "bknd"; // 语法错误 - 保留字
正确:
import { enumm } from "bknd";
entity("posts", {
status: enumm(["draft", "published"]),
});
使用 primary() 函数
错误:
import { primary } from "bknd"; // 在v0.20.0中未导出
正确:
// 主键是自动生成的
// 自定义格式:
entity("posts", { title: text() }, { primary_format: "uuid" });
错误的策略变量前缀
错误:
permissions: [{
permission: "data.entity.read",
filter: { user_id: { $eq: "@user.id" } }, // 错误前缀
}]
正确:
permissions: [{
permission: "data.entity.read",
filter: { user_id: { $eq: "@auth.user.id" } }, // 正确前缀
}]
用于持久化数据的内存数据库
症状: 重启后数据消失
错误:
npx bknd run --memory
# 或配置:{ url: ":memory:" }
正确:
npx bknd run --db-url "file:data.db"
# 或配置:{ url: "file:data.db" }
缺少防护启用
症状: 权限不工作,每个人都有访问权限
错误:
auth: {
guard: {
roles: { ... } // 防护未启用!
}
}
正确:
auth: {
guard: {
enabled: true, // 必需!
roles: { ... }
}
}
CORS Cookie问题
症状: 在Postman中身份验证工作,但在浏览器中不工作
修复:
// 服务器配置
server: {
cors: {
origin: ["http://localhost:5173"],
credentials: true,
}
}
auth: {
cookie: {
secure: false, // false用于HTTP开发
sameSite: "lax", // 不是 "strict" 用于OAuth
}
}
// 客户端获取
fetch(url, { credentials: "include" });
Filter 与 Allow/Deny 效果
症状: RLS过滤器返回所有记录而不是过滤
错误:
permissions: [{
permission: "data.entity.read",
effect: "allow", // 不会过滤!
condition: { user_id: { $eq: "@auth.user.id" } },
}]
正确:
permissions: [{
permission: "data.entity.read",
effect: "filter", // 过滤结果
filter: { user_id: { $eq: "@auth.user.id" } },
}]
快速诊断命令
检查服务器健康状态
curl http://localhost:3000/api/data
列出所有路由
npx bknd debug routes
检查配置路径
npx bknd debug paths
测试身份验证
# 登录
curl -X POST http://localhost:3000/api/auth/password/login \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","password":"password"}'
# 检查令牌
curl http://localhost:3000/api/auth/me \
-H "Authorization: Bearer <token>"
测试实体访问
# 未身份验证
curl http://localhost:3000/api/data/posts
# 已身份验证
curl http://localhost:3000/api/data/posts \
-H "Authorization: Bearer <token>"
检查模式
curl http://localhost:3000/api/system/schema
环境特定问题
开发环境
| 问题 | 解决方案 |
|---|---|
| 配置未加载 | 检查文件名:bknd.config.ts |
| 端口在使用中 | npx bknd run --port 3001 |
| 类型过时 | npx bknd types |
| 热重载不工作 | 重启服务器 |
生产环境
| 问题 | 解决方案 |
|---|---|
| JWT错误 | 设置 JWT_SECRET 环境变量(32+字符) |
| Cookie未设置 | secure: true 用于HTTPS |
| 500错误 | 检查日志,设置 NODE_ENV=production |
| D1未找到 | 检查wrangler.json绑定 |
无服务器环境
| 问题 | 解决方案 |
|---|---|
| 冷启动慢 | 使用边缘兼容数据库(D1, Turso) |
| 文件上传失败 | 使用S3/R2,不是本地存储 |
| SQLite原生错误 | 使用LibSQL或PostgreSQL |
基于症状的故障排除
“无法解析配置文件”
# 检查文件是否存在
ls bknd.config.*
# 明确指定
npx bknd run -c ./bknd.config.ts
“EADDRINUSE: 地址已在使用中”
# 查找进程
lsof -i :3000
# 使用不同端口
npx bknd run --port 3001
“spawn xdg-open ENOENT”
# 无头服务器 - 禁用浏览器打开
npx bknd run --no-open
“重启后数据消失”
# 检查输出中的内存模式
# 使用文件数据库
npx bknd run --db-url "file:data.db"
“ERR_UNSUPPORTED_ESM_URL_SCHEME” (Windows)
- 使用Node.js 18+
- 在package.json中添加
"type": "module" - 对配置使用
.mjs扩展
“TypeError: X 不是函数”
检查导入路径:
// SDK客户端
import { Api } from "bknd/client";
// 模式构建器
import { em, entity, text } from "bknd";
// 适配器
import { serve } from "bknd/adapter/node"; // Node
import { serve } from "bknd/adapter/cloudflare"; // CF Workers
做与不做
做:
- 首先检查服务器日志
- 验证实体名称是小写
- 使用curl测试前端调试之前
- 模式更改后重启服务器
- 使用
npx bknd debug routes用于404错误
不做:
- 使用
em()进行运行时查询 - 使用
:memory:用于持久化数据 - 忘记Api中的
storage: localStorage - 跳过防护的
enabled: true - 使用
@user.id(使用@auth.user.id)
相关技能
- bknd-debugging - 综合调试指南
- bknd-local-setup - 初始项目设置
- bknd-setup-auth - 身份验证配置
- bknd-assign-permissions - 权限配置
- bknd-api-discovery - 探索可用端点