UTF-8 边界误判速查
核心:完整文件合法,不代表任意字节切片都能作为“完整文本”严格解码。
为什么
- UTF-8 是变长编码,一个字符使用 1 到 4 个字节。
buffer.subarray(0, N)按字节截断,不认识字符边界。- 如果第 N 个字节落在字符中间,切片末尾就是不完整 UTF-8 序列。
new TextDecoder("utf-8", { fatal: true }).decode(slice)会把它当作错误。
本次故障链路
合法 SKILL.md -> 截取前 4096 字节 -> 最后一个中文字符只保留了部分字节 -> strict TextDecoder 抛错 -> isLikelyBinary() 返回 true -> 数据库存储 is_binary = 1 -> UI 显示“二进制文件暂不支持在线预览”
排查清单
- 完整 buffer 能否严格解码?
- 检测代码是否只解码固定长度样本?
- 样本是否可能截断多字节字符?
- 是否把“样本不完整”和“文件非法”混为一谈?
- 错误字段是在导入时写入,还是前端临时计算?
常见修复方向
- 对整个允许大小范围内的文件做严格 UTF-8 校验。
- 分块解码时使用流式语义,让 decoder 等待后续字节。
- 采样时回退到完整字符边界,再执行严格校验。