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

使用Next Auth自定义登录页时出现TypeError: resolver is not a function错误

解决NextAuth + T3栈中TypeError: resolver is not a function错误

访问登录页时触发Server Error,报错信息为TypeError: resolver is not a function,使用T3栈搭配NextAuth开发,相关代码如下:

相关代码

[...nextauth].ts

export const authOptions: NextAuthOptions = {
  // Include user.id on session
  callbacks: {
    session({ session, user }) {
      if (session.user) {
        session.user.id = user.id;
      }
      return session;
    },
  },
  // Configure one or more authentication providers
  adapter: PrismaAdapter(prisma),
  providers: [
    GoogleProvider({
      clientId: env.GOOGLE_CLIENT_ID,
      clientSecret: env.GOOGLE_CLIENT_SECRET,
    }),
    DiscordProvider({
      clientId: env.DISCORD_CLIENT_ID,
      clientSecret: env.DISCORD_CLIENT_SECRET,
    }),
    /**
     * ...add more providers here
     *
     * Most other providers require a bit more work than the Discord provider.
     * For example, the GitHub provider requires you to add the
     * `refresh_token_expires_in` field to the Account model. Refer to the
     * NextAuth.js docs for the provider you want to use. Example:
     * @see https://next-auth.js.org/providers/github
     */
  ],
  pages: {
    signIn: "/auth/signin",
  },
};

登录触发按钮

<ul>
... other buttons ...
  <li>
    <button onClick={() => {
      session ? signOut() : signIn()
    }} className="bla bla bla"/>
  </li>
</ul>

登录页组件

const SignIn: NextPage<{ providers: AppProps }> = ({ providers }) => {
    return (
        <>
            <main className="h-screen">
                <div className="container h-full px-6 py-24">
                    <div
                        className="g-6 flex h-full flex-wrap items-center justify-center lg:justify-between">
                        <div className="md:w-8/12 lg:ml-6 lg:w-5/12">
                            <form>
                                <div className="relative mb-6" data-te-input-wrapper-init>
                                    <input
                                        type="text"
                                        className="bla bla bla"
                                        id="exampleFormControlInput3"
                                        placeholder="Email address" />
                                    <label
                                        htmlFor="exampleFormControlInput3"
                                        className="bla bla bla"
                                    >Email address
                                    </label>
                                </div>
                                <div className="mb-6 flex items-center justify-between">
                                    <div className="bla bla bla">
                                        <input
                                            className="bla bla bla"
                                            type="checkbox"
                                            value=""
                                            id="exampleCheck3"
                                            checked />
                                        <label
                                            className="bla bla bla"
                                            htmlFor="checkBox">
                                            Remember me
                                        </label>

                                        <button
                                            type="submit"
                                            className="bla bla bla"
                                            data-te-ripple-init
                                            data-te-ripple-color="light">
                                            Send sign-in email link
                                        </button>

                                        <div
                                            className="bla bla bla">
                                            <p
                                                className="bla bla bla">
                                                OR
                                            </p>
                                        </div>

                                        <div>
                                            {Object.values(providers).map((provider) => (
                                                <button
                                                    data-te-ripple-init
                                                    data-te-ripple-color="light"
                                                    className="bla bla bla"
                                                    style={{ backgroundColor: "#3b5998" }}
                                                    key={provider.id}
                                                    onClick={() => signIn(provider.name, {
                                                        callbackUrl: `${window.location.origin}`
                                                    })}>
                                                    Sign in with {provider.name}
                                                </button>
                                            ))}
                                        </div>
                                    </div>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </main>
        </>
    );
};

export default SignIn;

export const getServerSideProps: GetServerSideProps = async () => {
    const providers = await getProviders();
    return {
        props: { providers },
    };
};

错误原因及修复方案

该错误主要由NextAuth路由导出不完整、getProviders调用参数缺失或signIn参数错误导致,修复步骤如下:

1. 完善[...nextauth].ts的路由导出

在[...nextauth].ts文件末尾添加NextAuth的路由导出,确保API路由能正确处理认证请求:

export default NextAuth(authOptions);

2. 修正登录页getServerSideProps的getProviders调用

getProviders需要传入配置好的authOptions才能正确获取登录提供商列表,修改登录页的getServerSideProps:

import { authOptions } from "../api/auth/[...nextauth]"; // 根据实际文件路径调整导入

export const getServerSideProps: GetServerSideProps = async () => {
    const providers = await getProviders(authOptions); // 传入authOptions参数
    return {
        props: { providers },
    };
};

3. 调整signIn的调用参数

登录页中调用signIn时,应使用provider.id而非provider.name,避免因提供商名称与ID不匹配导致的错误:

onClick={() => signIn(provider.id, {
    callbackUrl: `${window.location.origin}`
})}

额外检查项

  • 确保next-auth、@next-auth/prisma-adapter等依赖版本匹配,避免版本冲突引发的异常。
  • 验证环境变量(如GOOGLE_CLIENT_ID、DISCORD_CLIENT_ID等)是否正确加载,未正确初始化的提供商可能间接触发resolver错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 21:47:01