返回博客

AI 入门指南

“Not enough tokens”错误:它意味着什么以及如何修复

余额为空、速率限制、密钥错误、提示词过长或回答被截断:将你的 API 错误匹配到五种原因之一,运行快速检查,应用修复。

作者:CheapTokens Team发布于 更新于 6 分钟阅读

封面文字为“Not enough tokens?”,上方有五个标签:balance、rate、key、context、output
本页内容
  1. “tokens”可能指的三件事
  2. 1. 余额为空
  3. 2. 你触达了速率限制
  4. 3. 密钥错误
  5. 4. 提示词放不进上下文窗口
  6. 5. 回答被截断
  7. 同一问题,不同名称
  8. 看看实际返回什么
  9. 如果检查指向余额

“Not enough tokens”并不是一个错误。人们用这个说法指代五种不同的问题:余额为空、请求发送过快、密钥错误、提示词放不进模型的上下文窗口,或者回答触达输出上限并在句子中途停止。每种问题都有自己的修复方法,而区分它们最快的方式是看 HTTP 状态码和错误响应体,而不是消息的措辞。

在表格中找到你的症状,运行检查,应用修复。

你看到的现象 可能的原因 检查 修复
请求被拒绝;消息提到余额、计费或额度 余额为空 打开你的账户查看余额 充值余额,重试
能正常工作,然后成批失败,暂停后恢复 速率限制:同时或每分钟请求过多 等待一分钟后同一请求是否通过?你是否并行发送请求? 放慢速度,用递增的延迟重试
每个请求都立即失败,哪怕只有一行提示词 密钥错误、过期或输入有误,或基础 URL 错误 将代码中的密钥与账户中的密钥对比;检查 URL 粘贴一个新密钥,不要把它留在源代码中
短提示词正常,长提示词失败 提示词加上历史记录超出了上下文窗口 估算你发送的所有内容的大小 裁剪或总结历史记录,拆分文档,或选择窗口更大的模型
没有错误,但回答在句子中途结束 回答触达了输出上限 finish_reason 是 "length" 将 max_tokens 提高到模型的上限,要求更短的格式,或要求它继续

“tokens”可能指的三件事#

错误消息中的这个词指向三种不同的量。

  • 余额。 Token 是你付费购买的东西,所以“out of tokens”通常意味着“out of money”。在预付费服务中,这就是余额。
  • 每分钟限制。 限制可以按请求数或每分钟 token 数计算。触达其中一种,修复方法就是等待并减少一次发送的量。
  • 窗口大小。 上下文窗口是模型在一次请求中能读取的 token 数,包括你的提示词和它的回答。

还有一件它从不指代的事:API 密钥不是 token 的库存。密钥标识你的账户。耗尽的是它背后的余额,或附加在它上面的限制。如果你对这个单位本身还不熟悉,请先阅读 What is a token in AI?。

1. 余额为空#

DeepSeek 的 API 文档将 HTTP 402 Insufficient Balance 描述为“You have run out of balance”。Claude 的 API 使用 402 billing_error 表示计费和支付问题。名称不同,情况相同:钱没了。

CheapTokens 在原理上也是如此:预付费余额,按量付费,一个余额适用于所有模型。所以当出问题时,先看余额。这是一个十秒钟的检查,能排除最常见的原因。

2. 你触达了速率限制#

DeepSeek 将 HTTP 429 Rate Limit Reached 记录为请求发送过快,或超出了并发或 QPS 限制。修复方法是控制节奏:减少并行请求,并使用递增的重试延迟(1 秒、2 秒、4 秒),而不是猛打端点。

一个陷阱。Claude 的 API 在你达到所在层级的月度支出上限时也会返回 429 rate_limit_error,而且该响应没有 retry-after 头。因此,等待后始终不消失的 429 可能关乎钱,而不是速度。如果等待没有帮助,请回到原因 1。

3. 密钥错误#

HTTP 401 在两份文档中都是密钥问题:DeepSeek 将其列为 API 密钥错误,Claude 列为 authentication_error。常见原因包括复制密钥时带入了多余的空格或换行、密钥被删除或重新生成,以及密钥被发送到了错误的地址。来自一个服务的密钥在另一个服务的 URL 上无法使用。对于 CheapTokens,基础 URL 是 https://api.cheaptokens.dev/v1。

关于连接时可能遇到的其他错误,请参阅 Common connection errors and how to fix them。

4. 提示词放不进上下文窗口#

上下文窗口计算模型在一次请求中读取的所有内容:系统提示词、整个对话历史、你的新消息,以及为回答预留的空间。在 CheapTokens 上,我们目录中模型的窗口为:

模型 上下文窗口 每次回答的最大输出
DeepSeek-V4-Flash 380K 32,768 tokens
GLM-5.3-Flash 390K 8,192 tokens
MiniMax-M2.7 200K 8,192 tokens

聊天本身没有记忆。客户端在每次请求时都会重新发送整个历史记录,所以每个请求都比上一个更大。下面是一个虚构的聊天,用来展示增长(整数,仅作说明):系统提示词为 1,000 tokens,每一轮增加约 500 tokens 的问题和 1,500 tokens 的回答,共 2,000。

1,000 + 30 × 2,000 = 61,000 tokens

这是 30 轮之后历史记录的大小。这些 token 中的每一个在下一次请求时都会再次计为输入。第 31 次请求携带这 61,000 tokens 的历史记录加上新的 500 tokens 问题,因此其输入为 61,500 tokens。在 MiniMax-M2.7 上,加上 1,500 tokens 的回答,费用为 $0.0033。以下是同一请求在三个模型上的情况,并附上 OpenRouter 的价格作为对比:

模型 费用 OpenRouter
GLM-5.3-Flash $0.0013 $0.0027
DeepSeek-V4-Flash $0.0011 $0.0032
MiniMax-M2.7 $0.0033 $0.0203

总计 61,500 个输入 token 和 1,500 个输出 token。每 100 万 token 的价格为当前价格,会随我们的资费一同变动;OpenRouter 列显示相同工作负载的参考价格。

同一个聊天大约在一百轮后填满最小的窗口:

(200,000 − 1,000) / 2,000 = 99.5

当它溢出时,提供商会拒绝请求。状态码因提供商而异,所以要阅读错误响应体。例如,Claude 的 413 request_too_large 关乎请求的字节大小(Messages 为 32 MB),这是与 token 窗口不同的限制。

该怎么办:

  • 丢弃最旧的轮次,或用简短摘要替换它们。
  • 当任务只需要一章时,不要粘贴整个文档。
  • 如果你确实需要全文,请换用窗口更大的模型。

5. 回答被截断#

这里没有错误,这正是它令人困惑的原因。模型只是停止了,因为它达到了 max_tokens 或模型自身的输出上限。在 Chat Completions 格式中,标志是 choice 上的 finish_reason: "length"。

在 CheapTokens 上,DeepSeek-V4-Flash 每次回答最多可返回 32,768 tokens;GLM-5.3-Flash 和 MiniMax-M2.7 最多 8,192。如果你的 max_tokens 低于该值,请提高它。如果你已经达到上限,请拆分任务(“写第 1 部分,共 3 部分”)或要求模型从最后一句继续。

MiniMax-M2.7 的输出价格为每 1M tokens $0.15,在输出方面比 OpenRouter 更便宜。

同一问题,不同名称#

提供商对相同原因使用不同标签。以下是截至 2026 年 10 月 20 日其文档所述:

问题 DeepSeek API Claude API
余额为空 402 Insufficient Balance 402 billing_error
速率限制 429 Rate Limit Reached 429 rate_limit_error(也是层级的月度支出上限)
密钥错误 401 401 authentication_error
请求过大 未列为单独代码 413 request_too_large(字节,不是 tokens)
你自己设置的支出限制 未列出 400 invalid_request_error

来源:DeepSeek error codes、Claude API errors。两个页面都没有显示发布日期,所以检查日期是我们的。

要点:不要根据措辞猜测。错误以 JSON 返回,包含一个 error 对象,其中有 type 和 message。根据状态码和类型进行匹配,因为消息文本会变化。

看看实际返回什么#

这个片段会打印失败请求的状态码和响应体,以及成功请求的 finish_reason。这是一个诊断草图,不是测试日志:用你自己的密钥运行它,并阅读你得到的结果。

python
# Placeholders: YOUR_API_KEY, MODEL_ID (a model id you have access to)
from openai import OpenAI, APIStatusError

client = OpenAI(api_key="YOUR_API_KEY", base_url="https://api.cheaptokens.dev/v1")

try:
    r = client.chat.completions.create(
        model="MODEL_ID",
        messages=[{"role": "user", "content": "Write a long checklist."}],
        max_tokens=1000,
    )
except APIStatusError as e:
    # Read the status and the body, not the wording of the message
    print("status:", e.status_code)
    print("body:", e.body)
else:
    print("finish_reason:", r.choices[0].finish_reason)  # "length" = cut off
    print("usage:", r.usage)  # prompt_tokens and completion_tokens

如果检查指向余额#

充值余额并再次发送请求。CheapTokens 上的价格按模型固定,没有高峰时段,一个余额覆盖所有模型,因此你不需要为每个模型单独充值。当前费率在这里:

模型 上下文 输入 $/1M 输出 $/1M OpenRouter 输入 OpenRouter 输出
GLM-5.3-Flash reasoning 390K $0.02 $0.04 $0.0413 $0.0758
DeepSeek-V4-Flash 380K $0.015 $0.10 $0.0475 $0.1568
MiniMax-M2.7 180K $0.05 $0.15 $0.30 $1.20

价格以每 100 万 token 的美元金额计算。OpenRouter 数据仅供参考,可能会有变动。

在充值之前,将你自己的用量代入成本表。Top up your balance 当数字看起来合适时,如果你想先估算更大的工作量,请参阅 How to estimate the cost of an AI agent。