You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

页面加载时GraphQL 400错误排查(KeystoneJS+NextJS+Apollo)

节日快乐!看起来你遇到的问题是KeystoneJS的Apollo helpers组件在内部发送了一个不符合GraphQL规范的查询,导致出现400验证错误——虽然你自己写的查询最终成功了,但这些额外的错误请求还是挺闹心的。咱们一步步来排查解决:

问题根源分析

从错误信息里的提示Field "queries" of type "_ListQueries" must have a selection of subfields就能看出来:你并没有主动请求queries字段,但这个请求确实发生了。这大概率是@keystonejs/apollo-helpers里的KeystoneProvider或Query组件在初始化过程中,自动发送了一个内部默认查询,而这个查询没有指定queries字段的子选择项,触发了GraphQL的验证规则。

同时你在代码里同时用了@apollo/client的ApolloProvider和Keystone自己的KeystoneProvider,两者的客户端实例可能存在冲突,进一步加剧了这个问题。

解决方案步骤

1. 移除重复的Apollo Provider配置

KeystoneProvider已经内置了Apollo客户端的上下文管理,不需要再单独实例化ApolloClient和添加ApolloProvider。试试修改你的_app.tsx:

import { useReducer } from "react";
import { useRouter } from "next/router";
import { ThemeProvider } from "styled-components";
import { Query, KeystoneProvider } from "@keystonejs/apollo-helpers";
import { gql } from "@apollo/client";
import { primaryTheme } from "../styles/theme";
import GlobalStyle from "../styles/global";
import { initialState, globalReducer } from "../context/reducer";
import Meta from "../components/global/Meta";
import { Header } from "../components/global/Header";
import { globalContext } from "../context/contex";
import Footer from "../components/global/Footer";
import Loading from "../components/global/Loading";

const QUERY = gql`
 query {
 allOperations{
 id
 name
 }
 }
 `

const MyApp = ({ Component, pageProps }) => {
 const [store, dispatch] = useReducer(globalReducer, initialState);
 const router = useRouter();
 return (
 <KeystoneProvider clientOptions={{ uri: process.env.NEXT_PUBLIC_API_URL, fetchOptions: { mode: 'cors' } }}>
 <ThemeProvider theme={primaryTheme}>
 <Meta />
 {router.route !== "/" && <Header />}
 <Query query={QUERY} >
 {({ loading, data }) => {
 console.log(data);
 if(loading){
 return <Loading />
 } else {
 return <Component {...pageProps} />
 }}}
 </Query>
 <Footer />
 <GlobalStyle />
 </ThemeProvider>
 </KeystoneProvider>
 );
};

export default MyApp;

这里直接通过KeystoneProvider的clientOptions配置API地址,不再手动创建ApolloClient和添加ApolloProvider,避免双实例冲突。

2. 替换Keystone的Query组件为官方Apollo版本

如果上面的方法没效果,建议放弃使用@keystonejs/apollo-helpers的Query组件,改用@apollo/client的官方Query组件,完全掌控查询逻辑:

// 统一导入@apollo/client的组件
import { ApolloProvider, ApolloClient, InMemoryCache, HttpLink, gql, Query } from "@apollo/client";
// 移除@keystonejs/apollo-helpers的Query和KeystoneProvider

const client = new ApolloClient({
 ssrMode: true,
 cache: new InMemoryCache(),
 link: new HttpLink({ uri: process.env.NEXT_PUBLIC_API_URL, fetchOptions: { mode: 'cors' }, }),
});

// 其他代码不变,只保留ApolloProvider
const MyApp = ({ Component, pageProps }) => {
 const [store, dispatch] = useReducer(globalReducer, initialState);
 const router = useRouter();
 return (
 <ApolloProvider client={client}>
 <ThemeProvider theme={primaryTheme}>
 <Meta />
 {router.route !== "/" && <Header />}
 <Query query={QUERY} >
 {({ loading, data }) => {
 console.log(data);
 if(loading){
 return <Loading />
 } else {
 return <Component {...pageProps} />
 }}}
 </Query>
 <Footer />
 <GlobalStyle />
 </ThemeProvider>
 </ApolloProvider>
 );
};

这种方式完全使用官方Apollo Client,避免Keystone内部的默认查询干扰。

3. 升级KeystoneJS版本

这个错误很可能是旧版本@keystonejs/apollo-helpers的bug,试试升级Keystone相关依赖到最新稳定版:

npm update @keystonejs/keystone @keystonejs/apollo-helpers @keystonejs/app-graphql

4. 验证GraphQL Schema

确保你的Operation列表在Keystone中正确定义,allOperations查询确实存在并且包含id和name字段。你可以访问http://localhost:3000/admin/graphiql(Keystone自带的GraphiQL界面)手动执行你的查询,确认是否能正常返回结果。

额外说明

你提到前两次请求返回204,最后一次返回200,这说明你自己写的查询最终是成功的,前面的错误请求完全来自Keystone内部的默认操作。通过上面的步骤应该可以彻底消除这些错误请求,让页面加载更顺畅。

内容的提问来源于stack exchange,提问作者Bora ALAP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:04:31