当MongoDB集合开启了Schema Validation后,写入路径会在文档落盘前执行一次校验。返回代码1880说明文档没有通过集合上定义的验证规则,客户端拿到的错误通常会包含document failed validation之类信息。这个故障码并不代表MongoDB服务不可用,而是数据本身不符合约束。下面从触发场景、错误定位、验证规则和修复方案几个角度拆开说明。

故障码1880的触发条件与错误解读
MongoDB从3.2版本开始支持文档验证,4.0以后通过$jsonSchema表达更细粒度的规则。创建集合时可以指定validator,也可以对已有集合运行collMod添加校验器。校验动作发生在insert、update、findAndModify等写入操作中。如果集合的validationLevel为strict(默认),任何写入只要有一个文档不满足条件,整个操作报错并回滚;如果是moderate,只有已经存在的合法文档在更新后才需要进行校验。
代码1880本质上是Schema Validation失败的一种驱动层或服务端返回码。用户看到的具体输出可能是WriteError或BulkWriteError,其中的code字段为1880,errmsg包含Document failed validation。需要特别注意,单条插入和批量插入的报错形式不同,批量写入时可能部分成功,错误详情会列出失败的下标。定位时不要只看第一行信息,应完整打印异常对象或到日志中查找失败的文档内容。
Schema Validation如何判断文档是否合法
MongoDB的Schema Validation基于JSON Schema规范,但做了扩展。使用$jsonSchema时,可以限制字段类型、必填字段、枚举值、数值范围、字符串正则等。比如下面的规则要求name必须是字符串,age必须是整数且不低于18,email匹配邮箱格式。
db.createCollection("users", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name", "age", "email"],
properties: {
name: { bsonType: "string" },
age: { bsonType: "int", minimum: 18 },
email: { bsonType: "string", pattern: "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$" }
}
}
}
})
上面规则中如果插入的文档age使用了double类型18.0,也会触发1880,因为bsonType限制为int。这是很多人容易忽略的:MongoDB的数值类型区分int、long、double、decimal,数字字面量在shell中默认是double,需要显式使用NumberInt或NumberLong。校验器对类型非常敏感,任何细小差异都可能导致失败。
校验器不但能约束顶层字段,还能对嵌套文档和数组使用properties、items。validationAction默认是error,也就是验证失败直接返回错误。若设置为warn,则只会写入警告日志,文档仍然可以写入。排查时要确认当前集合的validationAction是error还是warn,如果是warn还是看到1880,通常说明有驱动或代理层在额外执行校验。
常见导致1880的原因与定位方法
最常见的原因有四种:字段缺失、类型不匹配、正则不通过、以及数组或嵌套对象结构不对。字段缺失包括大小写不一致,例如规则要求email,文档写成了Email。类型不匹配除了int与double差别,还包括null;如果字段存在但值是null,bsonType: string也会失败。
定位方法可以直接在shell里执行插入前用相同规则手动校验。可以通过db.getCollectionInfos({name: "users"})查看当前validator,再对照失败文档逐项排查。另一个办法是临时把validationAction改成warn,让文档写入,然后查看日志。生产环境修改集合参数前建议先在测试库复现,避免误操作。
// 查看集合的验证器
db.getCollectionInfos({ name: "users" }).forEach(function(coll) {
printjson(coll.options.validator);
});
// 临时关闭验证后再插入测试
db.runCommand({
collMod: "users",
validationLevel: "off"
});
批量写入时,可以给insertMany传入ordered: false,让所有文档都尝试写入,错误信息里会返回失败索引和对应的文档内容。单条写入失败时,也可以把要写入的文档先输出为JSON,再与validator规则逐字段比较。不要只看错误码1880本身,它只说明校验失败,不会告诉你具体哪个字段不符合规则。
修复方案:修改数据、调整验证器或跳过验证
修复方向有三个。第一是修改写入文档,让它符合当前集合的schema规则,适合验证器本身正确、业务数据写错的情况。第二是调整验证器,如果schema定义太严或与实际业务不匹配,可以用collMod更新validator。第三是在特殊迁移或修复历史数据时短暂跳过验证,但不应作为长期方案。
// 更新验证器:放宽age允许double类型
db.runCommand({
collMod: "users",
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name", "age"],
properties: {
name: { bsonType: "string" },
age: { bsonType: ["int", "double"], minimum: 18 }
}
}
},
validationLevel: "strict",
validationAction: "error"
});
如果只是临时让历史数据通过校验,可以将validationLevel设置为off,写入完成后再恢复。需要注意,MongoDB的验证只对校验器变更之后的新写入生效,修改validator不会自动校验已有文档。因此,调整规则后建议写一个脚本扫描已有数据,确认是否还有大量不符合新规则的文档,否则后续更新这些文档时仍会报1880。
另一个容易忽略的场景是upsert。findAndModify或update中的upsert会同时创建文档,创建的文档同样要经过validator。若查询条件生成的新文档缺少字段,就会失败。处理upsert时应该在更新操作符包含$set所有必填字段,或者使用$setOnInsert补齐默认值。
预防Schema Validation故障的实践建议
在线上集合启用严格校验前,建议先在开发环境模拟各类边界数据,包括null、缺字段、错误类型、超长字符串、非法枚举等。将validator规则用代码管理起来,与业务模型定义保持一致,避免数据库规则和应用层校验规则不统一。尤其是微服务架构中,多个服务写同一个集合时,schema变更需要通知所有写入方。
对于已有集合,可以用validationLevel: moderate来渐进式启用校验,先只约束新数据,确认无误后再严格化。如果业务允许,也可以把validationAction临时设为warn,观察一周日志,确认没有关键业务数据被拦截后再切回error。这样能降低代码1880突然出现的概率。
最后,监控上建议对MongoDB日志中的Document failed validation做关键字告警,同时把应用层异常中的code 1880单独统计。出现集中报错时,优先检查是否最近修改过validator,或者是否有新版本服务写入了新的字段结构。跨团队协作时,schema变更应该走评审流程,避免一方改规则导致另一方写入全部失败。
MongoDB故障码1880Schema Validation验证失败修改时间:2026-10-01 12:01:31