# Claude Code VOC Troubleshooting Playbook

This playbook helps Claude Code and maintainers quickly map live VOC collection symptoms to the right fix path. Use it when a real user conversation gets stuck, a platform collector reports the wrong state, or Claude Code does not know whether to retry, recharge, or switch tools.

## Fast Triage

| Symptom in Claude Code | Likely Cause | User-Facing State | First Fix Path | Do Not Do |
| --- | --- | --- | --- | --- |
| Douyin live says balance is insufficient, but the account has balance | Search API or keyword request failed and was classified as billing | `needs_keyword_fix` | Check Douyin API error classification and keyword repair | Do not show recharge link unless status is really `needs_recharge` |
| Douyin returns `社交平台接口请求错误` or HTTP 5xx | Upstream search or input issue | `needs_keyword_fix`, or auto-repair then `ok` | Normalize keyword, retry with a shorter natural keyword | Do not expose raw 5xx body to user |
| User passes `家居定制18元22元` and search is unstable | Compact keyword lacks natural search spacing | Usually auto-repaired | Normalize to `家居定制 18元 22元` | Do not require user to learn CLI flags |
| User passes empty `--keywords ""` | CLI parser receives an explicit empty value | `needs_keyword_fix` | Keep explicit empty as empty; do not fall back to default keywords | Do not silently search generic defaults |
| User asks “进入真实采集 live 模式” but workflow keeps deep-diving | Skill handoff rules are too weak | Should call platform live collector | Update deep-dive/business workflow skill instructions and `nextActions` | Do not keep asking 7-day validation questions |
| MCP output validation fails because warnings contain objects | Structured output schema expects strings | Tool call error | Normalize warnings at MCP server boundary | Do not remove evidence warnings entirely |
| Live collection says no token even after user configured one | Wrong working directory or unsupported credential source | `needs_token` | Check `.env.local` search path and `~/.claude/voc-credentials.json` | Do not print token |
| First report sounds final or overconfident | Report layer ignored evidence quality | `ok`, but poor UX | Enforce “初步判断 / 机会假设 / 待校准” and evidence quality | Do not write final business conclusions from first sample |

## Douyin Search Error Fix Pattern

When Douyin search fails, fix in this order:

1. Classify provider errors before building user messages.
2. Treat billing only as billing when the provider clearly says balance, quota, payment, or recharge.
3. Treat HTTP 400/422 and generic search 5xx as search/input repair.
4. Normalize keywords before calling the API.
5. Retry once with a shorter natural keyword.
6. If retry fails, return `needs_keyword_fix` with 2-3 concrete keyword examples.

Current key files:

| Concern | File |
| --- | --- |
| Provider error classification | `mcp/src/providers/douyin-api.js` |
| Keyword normalization and auto repair | `mcp/src/features/douyin-trend/live-collector.js` |
| User-facing status selection | `mcp/src/tools/douyin-trend-run.js` |
| MCP structured output normalization | `mcp/src/server.js` |
| Douyin skill behavior rules | `skills/douyin-trend-intelligence/SKILL.md` |
| Live mode reference | `skills/douyin-trend-intelligence/references/live-mode.md` |
| Manual live acceptance checks | `docs/live-manual-acceptance-checklist.md` |
| Regression smoke tests | `scripts/smoke-package.js` |

## Status Decision Rules

Use these states consistently:

| Condition | Status | Message Strategy |
| --- | --- | --- |
| No token configured | `needs_token` | Show payment/open link and token config path |
| Token invalid | `needs_valid_token` | Ask user to reconfigure token; show payment/open link only as support path |
| Clear balance/quota/payment issue | `needs_recharge` | Show recharge/payment link |
| Search input, empty keyword, overlong keyword, generic search 5xx | `needs_keyword_fix` | Give corrected keyword examples; no payment link |
| Token valid but no usable samples | `no_live_samples` | Suggest broader/narrower keywords; no payment link |
| Some samples collected but later billing blocked | `partial_needs_recharge` | Preserve partial report and show recharge link |
| Normal collection | `ok` | Return report body and evidence quality |

## Keyword Repair Recipes

Claude Code should prefer short, natural platform search phrases:

```text
品类 + 价格/问题 + 人群/场景
```

Examples:

```text
家居定制 18元 22元
家居定制 性价比 新客
全屋定制 方案 怎么选 避坑
家居定制 价格 怎么选
家居定制 对比 值不值
```

Repair rules:

- Insert spacing around Chinese and numbers: `家居定制18元22元` -> `家居定制 18元 22元`.
- Keep keywords under 60 characters.
- If price-specific search fails, try intent-specific search: `家居定制 性价比 新客`.
- If intent search fails, try behavior-specific search: `全屋定制 方案 怎么选 避坑`.
- If all fail, return `needs_keyword_fix` and tell the user what was tried.

## Implementation Checklist For Similar Bugs

When a new misclassification appears:

1. Reproduce with a small command or mocked provider response.
2. Add an error `kind` at provider boundary, for example `billing`, `auth`, `request`, `upstream_search`, `permission`.
3. Make the CLI/tool status choose from `kind`, not raw text only.
4. Normalize user input before API calls.
5. Add one automatic repair if it is safe and low-cost.
6. Add smoke coverage for both the bad path and the repaired path.
7. Update the skill instructions so Claude Code knows what to do in conversation.
8. Update manual acceptance docs with one command a trainer can run.
9. Run package smoke and build.

## Divergent Debugging Ideas

If the obvious fix does not work, branch into these checks:

- Credential source: is Claude Code running from the workspace that contains `.env.local`?
- MCP schema: did the tool return object warnings where the schema expects strings?
- CLI parsing: did `--keywords ""` become boolean `true` or an empty string?
- Encoding: did Chinese error text become mojibake or `????`, breaking regex matching?
- Upstream semantics: does provider return business error codes inside HTTP 200?
- Partial success: did videos collect but comments fail, requiring partial report instead of total failure?
- Report quality: did auto-repair succeed but report still say the original keyword?
- Skill routing: did the user ask for live collection, but a deep-dive skill kept control?
- Safety: does any output accidentally echo `VOC_TOKEN`, `Bearer`, or `r:...`?

## Verification Commands

Run these after changing collector behavior:

```powershell
node --check claude-code-voc-intelligence\mcp\src\providers\douyin-api.js
node --check claude-code-voc-intelligence\mcp\src\features\douyin-trend\live-collector.js
node --check claude-code-voc-intelligence\mcp\src\tools\douyin-trend-run.js
node --check claude-code-voc-intelligence\scripts\smoke-package.js
npm --prefix claude-code-voc-intelligence run mcp:smoke
npm --prefix claude-code-voc-intelligence run smoke:package
npm run claude-voc:build
```

Live manual check, only when a real token is configured:

```powershell
node .claude\plugins\voc-intelligence\mcp\src\tools\douyin-trend-run.js --collection-mode live --industry "家居定制" --business-type "全屋定制品牌" --target-audience "新客" --keywords "家居定制18元22元" --keyword-limit 1 --videos-per-keyword 1 --max-comment-pages 0 --cache-assets false --output "outputs/live-acceptance-douyin-keyword"
```

Expected:

- Compact keyword is normalized to `家居定制 18元 22元`.
- Search 5xx is auto-repaired or returned as `needs_keyword_fix`.
- Recharge URL appears only for token, valid-token, or real balance states.
- No token value appears in output.

