症状
错误“GraphQL 非空字段返回 null — 错误向上传播”指向一个明确的失效模式。下面依次给出症状、定位该原因的检查命令、根本原因、修复方案,以及证明修复有效的验证步骤。
可观察到的症状包括:
- 响应包含 “Cannot return null for non-nullable field User.name”
- 一个字段失败导致整个父对象变为 null
- 客户端收到部分为 null 的响应并带 errors
诊断
先在隔离环境中复现故障,再按顺序执行以下检查,逐步缩小范围。
步骤 1
curl -s -X POST https://api.example.com/graphql -H 'Content-Type: application/json' -d '{"query":"{ user { name } }"}'
错误路径会指出返回 null 的确切字段解析器。
步骤 2
git grep -n "User:\|name:" src/graphql/resolvers
在解析器内记录可确认是返回 null 还是抛错。
常见诱因(按出现频率排序):
- 解析器对 schema 中声明为非空的字段返回 null
- 异步解析器拒绝,错误越过了非空边界向上传播
- 数据源确实缺失该值,而 schema 却标为非空
根因
GraphQL 会沿非空字段向上传播 null:若非空字段解析为 null,错误会冒泡到最近的可空父级并使其为 null。这可保护客户端免于不完整对象,但可能置空的范围超出预期。
修复
修正解析器返回非空值,把确实可选的字段在 schema 中改为可空,并在解析器内处理错误,避免单个失败置空整个父级。
注意:为规避错误而把字段改为可空会把 null 处理推给每个客户端;值必需时应修正数据或解析器。
type User {
id: ID!
name: String! # non-null: resolver must never return null
bio: String # nullable: may be absent
}
// resolver: satisfy the non-null contract or throw a field error
User: {
name: (u) => {
if (!u.name) throw new Error('User.name is required');
return u.name;
},
}
验证
重跑查询并确认字段有值且 errors 为空;验证真实失败仍给出清晰错误。
修复后补充一条回归测试,复现原始症状,防止问题再次出现。
这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。