Apollo Server GraphQL报错:非空字段Mutation.createUser无法返回null问题排查
你的问题主要源于Apollo Server配置中的resolver参数名错误,同时还有resolver里的错误处理逻辑不当,下面是具体的问题分析和修复步骤:
1. 核心错误:Apollo Server未正确加载Resolver
在你的server.js中,创建ApolloServer实例时用了rootResolver作为参数键,但Apollo Server的构造函数要求的参数名是resolvers,这个错误直接导致所有查询和突变都没有对应的处理函数,默认返回null,触发非nullable字段的报错:
// 错误写法 const apolloServer = new ApolloServer({ typeDefs, rootResolver, }); // 正确写法 const apolloServer = new ApolloServer({ typeDefs, resolvers: rootResolver });
2. 修复Resolver的错误处理逻辑
你的createUser resolver里使用了res.status(500).send("Server error");,但Apollo的resolver函数中并没有res对象(这是Express的请求对象),这段代码会直接抛出错误,导致函数返回undefined(等同于null),进一步触发报错。
修改后的resolver应该重新抛出错误,让Apollo Server来处理错误响应:
const User = require("../../models/User"); const { ApolloError } = require('apollo-server-express'); // 引入Apollo专用错误类型 const createUser = async (args) => { try { const existingUser = await User.findOne({ address: args.loginInput.address }); if (existingUser) { throw new ApolloError("User already exists!", 'USER_ALREADY_EXISTS'); } const user = new User({ address: args.loginInput.address }); const result = await user.save(); // 确保返回结构严格匹配User类型定义 return { _id: result._id, address: result.address }; } catch (err) { console.error(err.message); throw err; // 重新抛出错误,交给Apollo Server统一处理 } }; module.exports = { createUser };
3. 确保Root Resolver的结构正确
你的rootResolver(即./graphql/resolvers/index.js)需要将Query和Mutation的resolvers组织到对应的键下,否则Apollo Server无法找到对应的处理函数:
const createUser = require('./createUser'); // 你的createUser resolver文件 const getUserById = require('./getUserById'); // 需要实现这个Query的resolver逻辑 module.exports = { Query: { getUserById }, Mutation: { createUser } };
4. 处理MongoID标量(可选但推荐)
虽然你提到换成ID!也有问题,但为了正确处理MongoDB的ObjectId,建议给MongoID标量添加解析器(在resolvers/index.js中添加):
const { GraphQLScalarType } = require('graphql'); const { ObjectId } = require('mongoose'); const MongoID = new GraphQLScalarType({ name: 'MongoID', description: 'MongoDB Object ID scalar type', serialize(value) { if (!(value instanceof ObjectId)) { throw new Error('MongoID can only serialize ObjectId values'); } return value.toString(); }, parseValue(value) { try { return ObjectId(value); } catch (err) { throw new Error('Invalid MongoID'); } }, parseLiteral(ast) { if (ast.kind !== 'StringValue') { throw new Error('MongoID can only be represented as a string'); } try { return ObjectId(ast.value); } catch (err) { throw new Error('Invalid MongoID'); } } }); module.exports = { MongoID, // 添加标量解析器 Query: { ... }, Mutation: { ... } };
验证修复效果
完成上述修改后重启服务器,重新执行createUser mutation,应该就能正常创建用户并返回正确的_id和address字段了。如果仍有问题,可以检查MongoDB连接是否正常,以及User模型的_id是否被Mongoose正确生成。
内容的提问来源于stack exchange,提问作者Ruham

