Vercel站点调用OpenAI text-curie-001接口返回500错误求助
Vercel部署站点调用OpenAI API返回500错误排查修复
问题背景
- 部署于Vercel的故事生成站点(访问地址:https://original-story-maker.vercel.app/)调用OpenAI
text-curie-001模型接口时返回500服务器错误,当前账号使用OpenAI免费额度 - 原接口请求代码如下:
import { Configuration, OpenAIApi } from "openai"; const configuration = new Configuration({ apiKey: process.env.OPENAI_API_KEY, }); const openai = new OpenAIApi(configuration); export default async function (req, res) { const completion = await openai.createCompletion("text-curie-001", { // prompt: generatePrompt(req.body.animal), prompt: "Write a story about " + req.body.employee + " wearing a " + req.body.wearing, temperature: 0.9, max_tokens: 720, top_p: 1.0, frequency_penalty: 0.0, presence_penalty: 0.0 }); res.status(200).json({ result: completion.data.choices[0].text }); }
- 错误日志、控制台截图如下:
: [WritableState], _events: [Object: null prototype], _eventsCount: 3, _maxListeners: undefined, _options: [Object], _ended: true, _ending: true, _redirectCount: 0, _redirects: [], _requestBodyLength: 142, _requestBodyBuffers: [], _onNativeResponse: [Function (anonymous)], _currentRequest: [Circular *1], _currentUrl: 'https://api.openai.com/v1/engines/text-curie-001/completions', [Symbol(kCapture)]: false }, [Symbol(kCapture)]: false, [Symbol(kNeedDrain)]: false, [Symbol(corked)]: 0, [Symbol(kOutHeaders)]: [Object: null prototype] { accept: [Array], 'content-type': [Array], 'user-agent': [Array], authorization: [Array], 'content-length': [Array], host: [Array] } }, response: { status: 401, statusText: 'Unauthorized', headers: { date: 'Tue, 21 Jun 2022 10:33:02 GMT', 'content-type': 'application/json; charset=utf-8', 'content-length': '280', connection: 'close', vary: 'Origin', 'x-request-id': '5534283309335fe6e2bf1c0ed0c68c1d', 'strict-transport-security': 'max-age=15724800; includeSubDomains' }, config: { transitional: [Object], adapter: [Function: httpAdapter], transformRequest: [Array], transformResponse: [Array], timeout: 0, xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, maxBodyLength: -1, validateStatus: [Function: validateStatus], headers: [Object], method: 'post', data: '{"prompt":"Write a story about jack wearing a wallet","temperature":0.9,"max_tokens":720,"top_p":1,"frequency_penalty":0,"presence_penalty":0}', url: 'https://api.openai.com/v1/engines/text-curie-001/completions' }, request: <ref *1> ClientRequest { _events: [Object: null prototype], _eventsCount: 7, _maxListeners: undefined, outputData: [], outputSize: 0, writable: true, destroyed: false, _last: true, chunkedEncoding: false, shouldKeepAlive: false, maxRequestsOnConnectionReached: false, _defaultKeepAlive: true, useChunkedEncodingByDefault: true, sendDate: false, _removedConnection: false, _removedContLen: false, _removedTE: false, _contentLength: null, _hasBody: true, _trailer: '', finished: true, _headerSent: true, _closed: false, socket: [TLSSocket], _header: 'POST /v1/engines/text-curie-001/completions HTTP/1.1\r\n' + 'Accept: application/json, text/plain, */*\r\n' + 'Content-Type: application/json\r\n' + 'User-Agent: OpenAI/NodeJS/2.0.0\r\n' + 'Authorization: Bearer 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\r\n' + 'Content-Length: 142\r\n' + 'Host: api.openai.com\r\n' + 'Connection: close\r\n' + '\r\n', _keepAliveTimeout: 0, _onPendingData: [Function: nop], agent: [Agent], socketPath: undefined, method: 'POST', maxHeaderSize: undefined, insecureHTTPParser: undefined, path: '/v1/engines/text-curie-001/completions', _ended: true, res: [IncomingMessage], aborted: false, timeoutCb: null, upgradeOrConnect: false, parser: null, maxHeadersCount: null, reusedSocket: false, host: 'api.openai.com', protocol: 'https:', _redirectable: [Writable], [Symbol(kCapture)]: false, [Symbol(kNeedDrain)]: false, [Symbol(corked)]: 0, [Symbol(kOutHeaders)]: [Object: null prototype] }, data: { error: [Object] } }, isAxiosError: true, toJSON: [Function: toJSON] } END RequestId: 427a64bf-859c-4f86-b3ca-33e5017aa24d REPORT RequestId: 427a64bf-859c-4f86-b3ca-33e5017aa24d Duration: 697.32 ms Billed Duration: 698 ms Memory Size: 1024 MB Max Memory Used: 45 MB RequestId: 427a64bf-859c-4f86-b3ca-33e5017aa24d Error: Runtime exited with error: exit status 1 Runtime.ExitError


根因定位
- 最高优先级风险:API密钥已完全泄露
日志中明文打印了完整的OpenAI API密钥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,该密钥已被公开,大概率已被OpenAI自动吊销,或被他人盗用,所有携带该密钥的请求都会返回401未授权错误。 - 401错误直接诱因
Vercel环境中配置的OPENAI_API_KEY值无效:要么是填入的密钥本身错误、已过期/被吊销,要么是配置环境变量后未重新部署,导致函数运行时读取不到正确的密钥值。 - 500错误直接诱因
代码未对OpenAI接口请求做异常捕获,当接口返回401错误时,未捕获的Promise异常直接导致Vercel Serverless函数进程崩溃退出,最终对外返回通用500错误,而非真实的401错误信息。
修复步骤
1. 立刻作废泄露的旧密钥
登录OpenAI控制台进入API密钥管理页面,找到上述已泄露的sk-tVy7开头的密钥,立即删除作废,避免被他人盗用消耗账号额度。
2. 生成新密钥并正确配置Vercel环境变量
- 在OpenAI控制台生成新的API密钥,生成后立即复制保存(新密钥仅展示一次,关闭页面后无法再次查看)
- 进入Vercel对应项目的
Settings - Environment Variables页面,新增/更新OPENAI_API_KEY变量,值填入刚生成的新密钥,生效范围勾选Production、Preview、Development全环境 - 注意:环境变量配置完成后必须手动触发一次重新部署,新的环境变量才会注入到函数运行环境中
3. 优化接口代码,增加异常处理与入参校验
将原有接口代码替换为以下版本,避免未捕获异常导致函数崩溃,同时方便后续排查问题:
import { Configuration, OpenAIApi } from "openai"; const configuration = new Configuration({ apiKey: process.env.OPENAI_API_KEY, }); const openai = new OpenAIApi(configuration); export default async function (req, res) { // 入参合法性校验 if (!req.body.employee?.trim() || !req.body.wearing?.trim()) { return res.status(400).json({ error: "缺少必要的生成参数" }); } if (!process.env.OPENAI_API_KEY) { return res.status(500).json({ error: "服务端API密钥未配置" }); } try { const completion = await openai.createCompletion("text-curie-001", { prompt: "Write a story about " + req.body.employee + " wearing a " + req.body.wearing, temperature: 0.9, max_tokens: 720, top_p: 1.0, frequency_penalty: 0.0, presence_penalty: 0.0 }); res.status(200).json({ result: completion.data.choices[0].text.trim() }); } catch (error) { // 打印详细错误日志用于排查,同时向前端返回结构化错误 console.error("OpenAI接口调用失败:", error.response?.data || error.message); const statusCode = error.response?.status || 500; res.status(statusCode).json({ error: error.response?.data?.error?.message || "服务内部错误,请稍后重试" }); } }
4. 重新部署验证
提交代码更新后触发Vercel自动部署,部署完成后重新测试功能即可。
内容的提问来源于stack exchange,提问作者Sambuxc
相关产品推荐
相关产品推荐

