Duix.Avatar 新增模特失败?SQLite3 布尔值报错三步修好
【免费下载链接】Duix-Avatar🚀 Truly open-source AI avatar(digital human) toolkit for offline video generation and digital human cloning.项目地址: https://gitcode.com/GitHub_Trending/he/Duix-Avatar
在 Duix.Avatar 里新增一个定制模特,视频传完、点击提交后,客户端日志里抛出这个错误,模特完全加不进去。原文是:
Error invoking remote method 'model/addModel': TypeError: SQLite3 can only bind numbers, strings, bigints, buffers, and null这条报错看着吓人,其实只是"最后一公里"的问题:一个布尔值被原样传进了 SQLite。
一条 INSERT 到底卡在哪
报错发生在往f2f_model表写模特记录这一步,实际执行的 SQL 是(取自客户端日志):
INSERT INTO f2f_model (name, video_path, audio_path, voice_id, created_at) VALUES ('aaa', '20250405012435008.mp4', 'origin_audio/20250405012435008.wav', false, 1743787484937)⚠️ 肇事参数就一个:第四个字段 voice_id 被绑定了false。better-sqlite3 的参数绑定白名单非常窄,一张表说清楚:
| 参数类型 | 能否绑定 |
|---|---|
| number、string、bigint、buffer | 能 |
| null | 能 |
| 布尔值(true / false) | 不能,直接抛上面这条 TypeError |
| undefined、对象、数组 | 不能,同样 TypeError |
为什么 false 不是合法值
类型不匹配:SQLite 绑定不认布尔
现象:建表语句里 voice_id 明明是整数列,写进去的却是布尔值。 证据:日志显示该语句绑定的值为布尔 false,而建表脚本src/main/db/sql.js中 voice_id 定义为INTEGER。 结论:SQLite 没有原生布尔类型,better-sqlite3 只接受 number/string/bigint/buffer/null 五类,布尔值直接越界报错。
上游断链:训练失败被 false 吞掉
现象:模特视频已经复制、音频也已分离,唯独 voice_id 这一环空了。 证据:日志里有train ~ res: { code: -1, msg: "'NoneType' object has no attribute 'send'" },说明 TTS 服务端的预处理接口调用失败,返回了 -1。 结论:语音训练入口 的train()在res.code !== 0时return false,上层 addModel 不校验,直接把 false 当 voiceId 递给了数据库——断链被静默吞到了数据库层才炸。
校验缺位:参数入库前没人把关
现象:用户最终只看到一句 "SQLite3 can only bind...",完全不知道是哪一个环节坏了。 证据:DAO 层 的insert()把五个参数原样交给stmt.run(...),执行前没有任何类型检查。 结论:voiceId不是数字也不是 null 就插不进去,整条 addModel 流程中断,而报错信息里甚至提不到 voiceId。
先止血,再根治
第 1 步·立即止血:把布尔值转成 null
在service/model.js的 insert 调用前改一行即可:
// 布尔 false 不落库,按"无语音模型"处理 voiceId: typeof voiceId === 'boolean' ? null : voiceId改完这步:SQLite 绑定报错消失,模特能正常入库,voice_id 为 null。
第 2 步·堵断链:训练失败改成直接抛错
病根在语音训练入口吞失败:TTS 服务预处理返回非 0 码(最常见的是 asr 连接被拒)时,它不抛错而是return false。把这一行换成:
if (res.code !== 0) throw new Error('Voice training failed: ' + res.msg)
改完这步:报错会从"SQLite 不能绑定"变成可读的 "Voice training failed: 'NoneType' object has no attribute 'send'",一眼看出是服务端 asr 没就绪,而不是去读数据库堆栈。
第 3 步·加保险:数据库层补一道类型检查
在 数据库连接层 的 run 包装里补最后防线:任一参数为布尔或 undefined 时,带出参数名直接抛错。改完这步:以后任何业务再误传布尔,报错信息会直接指到出问题的字段,排查不用翻三个文件。
下次怎么少踩坑
- 数据入库前统一过一遍"数字/字符串/整数/bigint/null 五类之一",不是就带字段名报错
- 上游 API 失败必须抛错,不要用 false 当哨兵值,它太容易被误读成"数据不存在"
- 新增模特前先校验视频有音轨且有人在说话,无声视频会让语音训练直接失败
- 排查客户端报错时优先看服务端 docker 日志,很多数据库错误本质是服务端返回了 -1
先改第 1 步那一行恢复模特新增,第 2、3 步的抛错改造排进下个版本跟进即可。
【免费下载链接】Duix-Avatar🚀 Truly open-source AI avatar(digital human) toolkit for offline video generation and digital human cloning.项目地址: https://gitcode.com/GitHub_Trending/he/Duix-Avatar
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考