目录

一个骗人的错误码:workbuddy code 11128 到底是什么意思

32

上游报 Illegal API invocation from an unapproved channel,文案说「渠道未获批准」,实际跟渠道毫无关系。

我用真实账号直连上游做了几轮对照实验,结论是:这是个通用拒绝码,至少有两种完全不同的成因,

而错误文案把人往错误方向引。

记录一下排查过程,也许能帮到踩同一个坑的人。

先说结论

你看到的现象真实成因怎么修
所有请求都 11128,连干净的也不例外请求头不合规补齐专有请求头
同一请求只改一个词组就过/不过词组触发内容校验改措辞

关键点:11128 不是「关键词错误」的专属错误码。 它更接近「服务器拒绝了这个请求,具体原因不告诉你」。

误判的代价很高——以为是关键词问题,就会去改 prompt、加过滤、换模型,全都不管用;以为是渠道问题,就会去查 API key、base URL、账号套餐,同样白费。

错误文案在骗你

Illegal API invocation from an unapproved channel

「unapproved channel」听起来像:你的反代插件没被授权、你的端点不在白名单、你的账号等级不够。

但实测发现:只带 Authorization 头时,连一个完全干净、不含任何敏感词的请求也返回 11128。

这就直接推翻了「渠道未授权」的解读——如果真是渠道问题,干净的请求也该过。

60 秒自证

别猜,做一次对照实验。用同一个账号、同一个模型,发两次请求,只改 system prompt 里的一个词:

// 请求 A
{
  "model": "<你的模型>",
  "stream": true,
  "messages": [
    { "role": "system", "content": "You are an AI agent powered by DeepSeek\u200B Harness." },
    { "role": "user", "content": "say OK" }
  ]
}
// 请求 B —— 只改 system 那一行
{
  "model": "<你的模型>",
  "stream": true,
  "messages": [
    { "role": "system", "content": "You are an AI agent." },
    { "role": "user", "content": "say OK" }
  ]
}

结果怎么读:

AB结论
❌ 11128✅ 200词组问题 → 改措辞
❌ 11128❌ 11128请求头/鉴权问题 → 改请求形状,跟内容无关
✅ 200✅ 200上游当前没拦这个词,不用修
✅ 200❌ 11128几乎不可能,先检查你是不是真改了想改的地方

成因一:请求头不合规

这是最容易误判的一种,因为它看起来完全不像请求头的问题。

WorkBuddy 网关要求一组专有请求头来标识客户端。只带 Authorization: Bearer <token> 会被判"request illegal"。

补齐这些(从 dsh-our-free-model 的 vendor/channel-pack/pack.js 里读出来的):

Authorization: Bearer <access_token>
Accept: text/event-stream
Content-Type: application/json

X-Domain: www.workbuddy.ai
X-Product: WorkBuddy
X-Product-Code: workbuddy
X-Agent-Purpose: conversation
X-IDE-Name: WorkBuddy
X-IDE-Type: WorkBuddy
X-IDE-Version: 5.5.2

X-Conversation-ID: <uuid>
X-Conversation-Message-ID: <uuid>
X-Conversation-Request-ID: <uuid>

另外两个请求形状要求,也是踩出来的:

项错的对的
路径/api/v1/chat/completions → 404/v2/chat/completions
流式非流式 → 11101"stream": true

实测证据

同一账号、同一模型、同一 body,只改请求头:

请求内容只带 Authorization补齐专有头
干净 system,无任何敏感词❌ 11128✅ 200
含触发词组❌ 11128✅ 200

缺头时连干净请求都被拦 —— 这就是「11128 不等于关键词问题」的直接证据。

成因二:词组触发内容校验

特征是:只改一个词组就过/不过。

怎么办

1. 先改措辞。如果 prompt 不需要那个词组,换个说法或者去掉。最简单也最稳。

2. 看你用的客户端有没有兼容性选项。不少反代客户端提供了 prompt 兼容设置,先读它的文档。

3. 自己维护反代的话,在请求发出前规范化 system prompt,别把应用内部的产品名原样发给第三方端点。

顺便说一句关于零宽字符(U+200B)这个流传的做法:插不可见字符确实能让朴素的子串扫描匹配不上。但我不建议把它当作正式方案,原因有两个:

一是它依赖对方的检测一直保持朴素,这个假设很脆弱;

二是绕开服务商的内容管控本身不该成为你代码的依赖。

如果某个词组触发了过滤,长期有效的做法是改词组或者联系服务商,而不是混淆它。

⚠️ 但有个坑要避

如果你确实要做 prompt 规范化:永远不要改文件路径里的内容。

D:\10_COD\DeepSeek Harness\resources\app.asar\dsh\     ← 必须保持逐字节一致

路径被改动,模型就会把坏路径传给工具调用,然后读文件报 ENOENT。

要改词组就用负向断言,跳过紧邻 / 或 \ 的情况:

const pattern = new RegExp(`(?<![\\\\/])DeepSeek[ \\u00A0]+Harness(?![\\\\/])`, 'g')

相关错误码对照

错误码含义怎么修
11101Non-stream chat request is currently not supported加 "stream": true
11128通用拒绝 —— 可能是请求头,也可能是内容先跑 60 秒自证
11133integer_below_min_value,max_tokens 太小调大 max_tokens
11140和 11128 同一族同 11128
6004usage exceeds frequency limit,限流换账号或等冷却
11102service info not found,通常是模型名/前缀映射不对检查模型映射

另外两个容易混淆的现象

现象真实原因
first message is not system prompt首条消息不是 system 角色,某些渠道强制要求
HTTP 200 但 content 为空、finish_reason: length推理模型把 max_tokens 全用来思考了,调到 ≥ 4096

我的实测结果(2026-10-22)

补对请求头之后,按规模递进测了 5 种,裸关键词一次都没被拦:

#请求形状结果
1小 system + 裸关键词✅ 200
2大 system(~11K 字符)+ 裸关键词✅ 200
3大 system(~11K)+ 零宽处理✅ 200
4大 system + 60 个 tool 定义 + 裸关键词✅ 200
5大 system + 60 个 tool + 零宽处理✅ 200

也就是说,成因二当前(至少对我这个账号)复现不出来。上游可能已经放宽了那个词。

所以这份记录的价值不在「教你怎么绕」,而在:

  • 告诉你 11128 有两种成因,别猜错方向;
  • 给你一个 60 秒能做完的判别方法;
  • 如果你撞的是成因一,那问题根本不在内容上。

那些不是原因的东西

排查时被错误怀疑过的(已逐一排除):

被怀疑的实际
渠道/端点没被批准文案说 channel,但跟渠道无关
API key 错了key 错是 401,不是 11128
账号等级不够额度问题表现为 quota 类错误,不是 11128
请求体太大用 ~11K prompt + 60 个 tool 测过,没被拒
被限流了那是 6004,另一个码
服务器挂了11128 是带完整 JSON body 的主动拒绝

最后

这些结论全部来自 2026-10-22 一轮真实上游测试(8 个计费请求),针对的是某一个具体反代实现。上游行为随时可能变。

错误码本身没有公开文档,都是我按实际响应反推的。如果你发现和你的情况不符,欢迎在下面留言——特别是如果你能稳定复现「成因二」,那个数据很有价值。


相关代码和完整测试记录:dsh-workbuddy-fix(先说明:如果按上面 60 秒自证发现是请求头问题,那个插件帮不上,不用装)。