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

部署至Vercel/AWS Amplify时出现[CLIENT_FETCH_ERROR] Unexpected token错误

问题:部署NextAuth到Vercel/AWS Amplify后出现[CLIENT_FETCH_ERROR] Unexpected token错误

本地运行完全正常,但部署到Vercel或AWS Amplify后,出现**[CLIENT_FETCH_ERROR] Unexpected token**错误。

Vercel环境变量

NODE_ENV="production"
NEXTAUTH_URL="vercel_url"
NEXTAUTH_SECRET="VZsVRu8vqgkiqz53GrohF/EQS59pN1m46nVunlTemXA="
BACKEND="django_api_url"
JWT_SECRET="JmG3h0sKkM0DlUbIPybA0QvtqKuxLex7Wqa9btciNXU="

NEXTAUTH_SECRET和JWT_SECRET均通过openssl生成。

[...nextauth].ts代码

import NextAuth from 'next-auth'
import type { NextAuthOptions } from 'next-auth'
import CredentialsProvider from 'next-auth/providers/credentials'
import axios, { AxiosResponse } from 'axios'

import { AuthResponse, combinedJWT } from './types'

const refreshAccessToken = async (token: combinedJWT) => {
  const response: AxiosResponse<{ access: string }, any> = await axios.post(
    `${process.env.BACKEND}/api/token/refresh/`,
    {
      refresh: token.refreshToken,
    }
  )

  if (response.status === 200 && response.data.access) {
    console.log('access: ' + response.data.access)
    return {
      ...token,
      accessToken: response.data.access,
      expiresAt: Date.now() + 5000,
    }
  }

  return {
    ...token,
    error: 'RefreshAccessTokenError',
  }
}

export const authOptions = {
  providers: [
    CredentialsProvider({
      name: 'Credentials',
      credentials: {
        otp: { label: 'otp', type: 'text' },
        userId: { label: 'UserId', type: 'text' },
      },
      async authorize(credentials) {
        const user: AxiosResponse<AuthResponse> = await axios.post(
          `${process.env.BACKEND}/auth/login/${credentials?.userId}/`,
          { otp: credentials?.otp }
        )

        if (user.status === 200) {
          return {
            id: user.data.id,
            username: user.data.username,
            email: user.data.email,
            user_type: user.data.user_type,
            tokens: user.data.tokens,
          }
        } else {
          return null
        }
      },
    }),
  ],
  secret: process.env.JWT_SECRET,
  pages: {
    signIn: '/signin',
  },
  callbacks: {
    async jwt({ token, user }: any) {
      if (user) {
        return {
          ...token,
          accessToken: user.tokens.access,
          refreshToken: user.tokens.refresh,
          expiresAt: Date.now() + 5000,
          userType: user.user_type,
          name: user.username,
          email: user.email,
          userId: user.id,
        }
      }

      if (Date.now() < token.expiresAt) {
        return token
      }

      const newToken = await refreshAccessToken(token)
      return newToken
    },
    async session({ session, token, user }: any) {
      session.accessToken = token.accessToken

      if (user) {
        session.user = {
          ...user,
          id: token.userId,
          name: token.name,
          user_type: token.userType,
        }
      } else {
        session.user = {
          id: token.userId,
          name: token.name,
          user_type: token.userType,
        }
      }

      return session
    },
  },
  debug: process.env.NODE_ENV === 'development',
} as NextAuthOptions

export default NextAuth(authOptions)

Vercel运行时日志

2022-10-30T12:27:31.291Z    057bedbb-fa76-45dc-8f6b-1b352da0d3b5    ERROR   [next-auth][error][CLIENT_FETCH_ERROR] 
https://next-auth.js.org/errors#client_fetch_error invalid json response body at https://ob-client-v2.vercel.app/api/auth/session reason: Unexpected token < in JSON at position 0 {
  error: {
    message: 'invalid json response body at https://ob-client-v2.vercel.app/api/auth/session reason: Unexpected token < in JSON at position 0',
    stack: 'FetchError: invalid json response body at https://ob-client-v2.vercel.app/api/auth/session reason: Unexpected token < in JSON at position 0\n' +
      '    at /var/task/node_modules/next/dist/compiled/node-fetch/index.js:1:51220\n' +
      '    at processTicksAndRejections (node:internal/process/task_queues:96:5)',
    name: 'FetchError'
  },
  url: 'https://ob-client-v2.vercel.app/api/auth/session',
  message: 'invalid json response body at https://ob-client-v2.vercel.app/api/auth/session reason: Unexpected token < in JSON at position 0'
}

解决方案

  • 修正NEXTAUTH_URL配置:将环境变量中的NEXTAUTH_URL替换为实际的Vercel部署域名(比如https://ob-client-v2.vercel.app),占位符会导致NextAuth生成错误的会话端点,请求返回HTML错误页面而非JSON。
  • 验证后端API可访问性:确认BACKEND指向的Django API在生产环境中能被Vercel服务器访问,检查API的CORS设置是否允许Vercel域名的请求。
  • 检查NextAuth的secret配置:虽然你用了JWT_SECRET作为secret,但建议使用官方推荐的NEXTAUTH_SECRET,同时确保环境变量中的值没有多余引号或格式错误。
  • 调整令牌过期时间:当前代码中expiresAt设置为5秒后过期,会导致频繁触发令牌刷新,建议改为与后端JWT实际过期时间匹配的值(如15分钟:Date.now() + 15 * 60 * 1000),避免因频繁请求导致后端返回错误。
  • 确认API路由部署状态:在Vercel控制台检查/api/auth/相关路由是否成功部署,无构建错误,若路由未部署会返回404 HTML页面,引发JSON解析失败。

内容的提问来源于stack exchange,提问作者χerфmiи

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 23:26:06