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

NextJS开发登录系统时遭遇AxiosError: ERR_BAD_REQUEST错误求助

问题:NextJS注册系统持续触发Axios 400错误

AxiosError {message: 'Request failed with status code 400', name: 'AxiosError', code: 'ERR_BAD_REQUEST', config: {…}, request: XMLHttpRequest, …}

相关代码片段

客户端(RegisterPage)

const [authState, setAuthState] = useState({
    name: "",
    email: "",
    password: "",
    password_confirmation: "",
  });

  const [loading, setLoading] = useState<boolean>(false);
  const [errors, setErrors] = useState<registerErrorType>({});

  const submitForm = () => {
    setLoading(true);
    axios
      .post("http://localhost:3000/api/auth/register", authState)
      .then((res) => {
        setLoading(false);
        const response = res?.data;
        // debugger;
        if (response?.status == 200) {
          console.log("User created successfully");
        } else if (response?.status == 400) {
          setErrors(response?.errors);
        }
      })
      .catch((error: any) => {
        console.error("Axios request error:", error);
        setLoading(false);
      });
  };

服务端(RegisterPage API)

export async function POST(request: NextRequest) {
  try {
    const body = await request.json();
    const validator = vine.compile(registerSchema);
    const output = await validator.validate(body);
    validator.errorReporter = () => new ErrorReporter();
    // check if email already existes
    const user = await User.findOne({ email: output.email });
    if (user) {
      return NextResponse.json(
        {
          status: 400,
          errors: {
            email: "Email is already exists",
          },
        },
        { status: 200 }
      );
    } else {
      // Encrypt the password
      const salt = bcrypt.genSaltSync(10);
      output.password = bcrypt.hashSync(output.password, salt);
      await User.create(output);
      return NextResponse.json(
        { status: 200, message: "User created successfully" },
        { status: 200 }
      );
    }
  } catch (error) {
    if (error instanceof errors.E_VALIDATION_ERROR) {
      return NextResponse.json(
        { status: 400, errors: error.messages },
        { status: 400 }
      );
    }
  }
}

问题排查与修复

1. 响应状态码不匹配导致Axios进入catch

当邮箱已存在时,服务端返回的HTTP状态码是200,但响应体status字段设为400。Axios以HTTP状态码判断请求是否成功,非2xx状态码会直接进入catch块,无法走到then内的错误处理逻辑。

修复:将邮箱已存在的响应状态码改为400,与响应体字段保持一致:

if (user) {
  return NextResponse.json(
    {
      status: 400,
      errors: {
        email: "Email already exists", // 修正语法错误
      },
    },
    { status: 400 } // 把200改为400
  );
}

2. Vine验证器配置顺序错误

先执行validator.validate(body)再设置errorReporter,会导致自定义错误报告器不生效,验证失败时抛出的错误不符合预期。

修复:调整顺序,先配置错误报告器再执行验证:

const validator = vine.compile(registerSchema);
validator.errorReporter = () => new ErrorReporter(); // 移到validate之前
const output = await validator.validate(body);

3. 未处理兜底异常

服务端catch块仅处理E_VALIDATION_ERROR,其他异常(如数据库连接失败)会导致函数无返回值,NextJS默认返回500状态码,同样触发Axios错误。

修复:添加兜底返回逻辑:

catch (error) {
  if (error instanceof errors.E_VALIDATION_ERROR) {
    return NextResponse.json(
      { status: 400, errors: error.messages },
      { status: 400 }
    );
  }
  // 处理其他未捕获异常
  return NextResponse.json(
    { status: 500, errors: { server: "Internal server error" } },
    { status: 500 }
  );
}

4. 客户端错误处理优化

当前客户端仅在响应体status为400时设置错误,但服务端返回HTTP 400时会直接进入catch,需在catch内提取服务端错误信息:

.catch((error: any) => {
  console.error("Axios request error:", error);
  setLoading(false);
  // 提取服务端返回的错误
  if (error.response?.data?.errors) {
    setErrors(error.response.data.errors);
  } else {
    setErrors({ server: error.message || "Request failed" });
  }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 21:56:05