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

Flutter发送POST请求遇500错误,OpenAI接口调用异常排查

Flutter调用Express后端OpenAI接口的500错误排查

问题描述

在Flutter中向Express后端的/generate接口发送POST请求时收到500错误。最初后端期望接收字符串类型的question参数,但实际传入的prompt是List<Map<String, dynamic>>类型。修改后端直接将question作为messages传入OpenAI接口后,后端日志出现BadRequestError: 400 'messages' is a required property,无法定位问题。


初始代码与错误

初始后端代码

require("dotenv").config();

const express = require("express");
const cors = require("cors");
const app = express();
const PORT = process.env.PORT || 5000;
const OpenAI = require("openai");

const openai = new OpenAI({
  apiKey: process.env.OPENAI_KEY,
});

app.use(
  cors({
    origin: ["https://xxxxx.vercel.app", "http://localhost:3000"],
  })
);
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.get("/", (req, res) => res.send("Hello World!"));

// Get answer from GPT model
app.post("/generate", async (req, res) => {
  const { question } = req.body;
  try {
    const response = await openai.chat.completions.create({
      messages: [
        {
          role: "system",
          content: "xxxxxxxxxxxxxx",
        },
        { role: "user", content: question },
      ],
      model: "gpt-3.5-turbo",
      temperature: 0.2
    });
    const answer = response.choices[0].message.content;
    res.status(200).json({ answer: answer });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Error retrieving answer" });
  }
});

app.listen(PORT, () => console.log(`Server up at PORT:${PORT}`));

Flutter请求代码

final url = Uri.parse('https://xxxxx-express-api.onrender.com/generate');
final body = jsonEncode({'question': prompt});
final response = await http.post(url, body: body);
print(response.statusCode);

初始错误日志

BadRequestError: 400 'content' is a required property - 'messages.1'

修改后的代码与错误

修改后的后端代码

require("dotenv").config();

const express = require("express");
const cors = require("cors");
const app = express();
const PORT = process.env.PORT || 5000;
const OpenAI = require("openai");

const openai = new OpenAI({
  apiKey: process.env.OPENAI_KEY,
});

app.use(
  cors({
    origin: ["https://xxxxx.vercel.app", "http://localhost:3000"],
  })
);
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.get("/", (req, res) => res.send("Hello World!"));

// Get answer from GPT model
app.post("/generate", async (req, res) => {
  const { question } = req.body;
  try {
    const response = await openai.chat.completions.create({
      messages: question,
      model: "gpt-3.5-turbo",
      temperature: 0.2
    });
    const answer = response.choices[0].message.content;
    res.status(200).json({ answer: answer });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Error retrieving answer" });
  }
});

app.listen(PORT, () => console.log(`Server up at PORT:${PORT}`));

修改后的错误日志

Oct 31 01:27:06 PM  BadRequestError: 400 'messages' is a required property
Oct 31 01:27:06 PM      at APIError.generate (/opt/render/project/src/node_modules/openai/error.js:43:20)
Oct 31 01:27:06 PM      at OpenAI.makeStatusError (/opt/render/project/src/node_modules/openai/core.js:248:33)
Oct 31 01:27:06 PM      at OpenAI.makeRequest (/opt/render/project/src/node_modules/openai/core.js:287:30)
Oct 31 01:27:06 PM      at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
Oct 31 01:27:06 PM      at async /opt/render/project/src/index.js:23:22 {
Oct 31 01:27:06 PM    status: 400,
Oct 31 01:27:06 PM    headers: {
Oct 31 01:27:06 PM      'access-control-allow-origin': '*',
Oct 31 01:27:06 PM      'alt-svc': 'h3=":443"; ma=86400',
Oct 31 01:27:06 PM      'cf-cache-status': 'DYNAMIC',
Oct 31 01:27:06 PM      'cf-ray': 'xxx-SIN',
Oct 31 01:27:06 PM      connection: 'keep-alive',
Oct 31 01:27:06 PM      'content-length': '146',
Oct 31 01:27:06 PM      'content-type': 'application/json',
Oct 31 01:27:06 PM      date: 'Tue, 31 Oct 2023 07:57:06 GMT',
Oct 31 01:27:06 PM      'openai-organization': 'user-xxx',
Oct 31 01:27:06 PM      'openai-processing-ms': '4',
Oct 31 01:27:06 PM      'openai-version': '2020-10-01',
Oct 31 01:27:06 PM      server: 'cloudflare',
Oct 31 01:27:06 PM      'strict-transport-security': 'max-age=15724800; includeSubDomains',
Oct 31 01:27:06 PM      'x-ratelimit-limit-requests': '3500',
Oct 31 01:27:06 PM      'x-ratelimit-limit-tokens': '90000',
Oct 31 01:27:06 PM      'x-ratelimit-remaining-requests': '3499',
Oct 31 01:27:06 PM      'x-ratelimit-remaining-tokens': '89983',
Oct 31 01:27:06 PM      'x-ratelimit-reset-requests': '17ms',
Oct 31 01:27:06 PM      'x-ratelimit-reset-tokens': '10ms',
Oct 31 01:27:06 PM      'x-request-id': 'xxx'
Oct 31 01:27:06 PM    },
Oct 31 01:27:06 PM    error: {
Oct 31 01:27:06 PM      message: "'messages' is a required property",
Oct 31 01:27:06 PM      type: 'invalid_request_error',
Oct 31 01:27:06 PM      param: null,
Oct 31 01:27:06 PM      code: null
Oct 31 01:27:06 PM    },
Oct 31 01:27:06 PM    code: null,
Oct 31 01:27:06 PM    param: null,
Oct 31 01:27:06 PM    type: 'invalid_request_error'
Oct 31 01:27:06 PM  }

问题排查与解决方案

核心问题分析

  1. 初始错误原因:后端期望question是字符串,但Flutter传入的是对话消息数组,导致{ role: "user", content: question }中content格式不符合要求,触发OpenAI的'content' is a required property错误。
  2. 修改后错误原因:Flutter请求未设置Content-Type: application/json,导致Express的express.json()中间件无法正确解析请求体,req.body.question为undefined,进而导致OpenAI接口收到的messages参数缺失。

具体修复步骤

1. 修正Flutter请求的Content-Type

final url = Uri.parse('https://xxxxx-express-api.onrender.com/generate');
final body = jsonEncode({'question': prompt});
final response = await http.post(
  url,
  body: body,
  headers: {'Content-Type': 'application/json'}, // 新增JSON类型头
);
print(response.statusCode);

2. 后端添加参数验证日志

在/generate接口中添加日志,确认接收的参数格式:

app.post("/generate", async (req, res) => {
  const { question } = req.body;
  // 新增日志验证参数
  console.log("Received question:", question);
  console.log("Is array:", Array.isArray(question));
  
  try {
    const response = await openai.chat.completions.create({
      messages: question,
      model: "gpt-3.5-turbo",
      temperature: 0.2
    });
    const answer = response.choices[0].message.content;
    res.status(200).json({ answer: answer });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: "Error retrieving answer" });
  }
});

3. 确保消息数组符合OpenAI格式

OpenAI要求messages是数组,每个元素必须包含role(system/user/assistant)和content(字符串)字段。如果Flutter传入的prompt不含系统消息,可在后端补充:

const messages = [
  {
    role: "system",
    content: "xxxxxxxxxxxxxx", // 保留原系统消息
  },
  ...question // 展开用户传入的消息数组
];

const response = await openai.chat.completions.create({
  messages: messages,
  model: "gpt-3.5-turbo",
  temperature: 0.2
});

验证修复

重新部署后端和Flutter应用,发送请求后检查后端日志,确认question为正确的数组格式,若仍有错误则根据日志调整参数格式。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 04:28:12