故障排查¶
FAQ 格式:每条按 问题 → 原因 → 修复 组织。完整的错误语义参考(状态码、终态、 重试纪律)见响应与错误与 限流与错误。
裸请求 API 遭遇 Cloudflare 403¶
问题:手工 curl / 脚本请求 www.perplexity.ai 的 REST 端点返回 403 和
Cloudflare 质询页——即使带上了从浏览器复制的 cookie——而同样的端点走工具却正常。
原因:Cloudflare 挡在站点前面,cf_clearance / __cf_bm 与浏览器的 TLS 指纹
绑定。裸客户端指纹不匹配,质询即触发。工具能过是因为用 Python urllib + 从浏览器
导入的 cookie + 桌面 Chrome User-Agent
(pplx_export/core/http/cookie_transport.py:29)。Cloudflare 在风控限流时也可能
403——那时响应带同样的质询形态。
修复:
- 不要绕过工具的 transport;用
pplx-export/pplx-ask发起调用,不要写临时脚本。 - 工具内部把 HTTP 200 但非 JSON 的响应体(Cloudflare 过场页)归类为传输错误而非数据
(
pplx_export/core/http/cookie_transport.py:133)。 - 工具内若开始出现 403,先放慢节奏(见限流)并刷新 cookie; 持续质询则需在浏览器里重新登录。
- 注意 403 的两副面孔:Cloudflare 风控质询(放慢即可消退)与 API 级 403(cookie 失效——立即抛出、不退避,见下一节)。设计页映射的是后者 (rate-limiting-errors.md)。
背景:API 认证。
401 错误 / cookie 过期¶
问题:命令因鉴权错误失败——pplx-export 抛 AuthTransportError: 鉴权失败 401,
或 pplx-ask ask 以 HTTP 401/403 的「更新 cookie」提示退出。
原因:会话 cookie 已过期或失效。401/403 被视为鉴权失败并立即抛出——不退避,
因为退避无法自愈死掉的会话(pplx_export/core/http/cookie_transport.py:82;
pplx_export/core/errors.py:68)。batch 在连续 3 次鉴权失败后还会 fail-fast,
避免死 cookie 烧穿整个队列。
修复:
- 在浏览器里重新登录(或重新打开站点),让会话 cookie 续期。
- 刷新工具的 cookie 缓存。
<out>/index/.cookies.json在 12 小时新鲜期内会被复用 (pplx_export/core/cookies.py:39),所以重新登录后二选一: - 带
--cookies-from <browser>跑一次,强制从浏览器重新导入;或 - 删除
<out>/index/.cookies.json,让下次运行自动重新导入。 - 每次校验成功的运行都会重存缓存(
pplx_export/commands/common.py:150),日常运行 自行保持新鲜。
导出用了错误的账户(多账户)¶
问题:归档线程是用错误账户的会话抓取的——例如 --account alice 的运行实际以
bob 拉数据,或归档里出现不属于目标账户的线程。
原因:同一浏览器登录多个账户时,活跃的会话令牌
(__Secure-next-auth.session-token)可能属于另一个账户。若目标账户的 email
未在用户级配置中登记,工具无法识别,只能记一条 warning。
工具的预防机制(pplx_export/commands/common.py:93):启动时 transport 调
GET /api/auth/session,把实时 email 与登记值比对。不匹配时自动枚举浏览器里各账户
的会话 cookie(__Secure-pplx.session.<user_id>),逐个替换活跃令牌并探测 session,
直到命中目标 email(pplx_export/commands/common.py:190;
pplx_export/core/cookies.py:97)。无令牌匹配时命令带清晰报错中止——绝不以错误
账户静默继续。
修复:
- 在
[accounts.<name>]下登记每个账户的email(见配置), 并显式传--account。 - 看启动日志行
[auth] cookie 来源 …,当前账户: …——它在抓取任何数据前报出实时 会话 email。 - 审计既有归档:每个线程的
thread.json带export_via字段,记录执行导出的账户 (pplx_export/sites/perplexity/fs_writer.py:229)。pplx-export sync-deleted也用该字段选择在线验证的账户。
「找不到配置文件」——降级模式¶
问题:启动 warning 提示未找到用户级配置文件、命令以降级模式运行;或显式
--account alice 报错并指向 config.example.toml。
原因:三个查找位置都没有配置文件——--config PATH、环境变量
PPLX_EXPORT_CONFIG、默认 ~/.config/pplx-export/config.toml
(pplx_export/config.py:113)。两种相关但不同的情形:显式指定的配置路径不
存在会抛 ConfigError;配置损坏(无法解析)一律抛 ConfigError——坏配置绝不
静默降级。
降级模式的影响:
- 账户注册表为空,cookie 归属校验跳过并 warning,命令以占位账户
default运行 (pplx_export/commands/common.py:51)。显式--account则直接报错。 pplx-ask ask跳过自动移入 BOT 空间(结果 JSON 中moved_to_bot保持false), 遥测携带空 user id;发问与归档本身照常工作。- 归档落在按用户名回退的账户目录下。
修复:把 config.example.toml 复制为 ~/.config/pplx-export/config.toml,填好
[accounts.<name>](display_name / email / user_id)、[bot_space] 与
default_account —— 见配置。
ENTRY_EXPIRED 与 ENTRY_DELETED 的区别¶
问题:导出或增量同步某线程时报告 ENTRY_EXPIRED 或 ENTRY_DELETED,且该线程
再也无法抓取。
原因:两者都以 GET /rest/thread/<uuid> 的 HTTP 400 返回、错误码不同,且同为
终态——线程在平台上已不存在:
| 错误码 | 含义 | 工具映射 | 终态 |
|---|---|---|---|
ENTRY_EXPIRED |
平台清除了该线程(约 3 个月保留期) | EntryExpiredError(pplx_export/core/errors.py:24) |
expired |
ENTRY_DELETED |
线程被用户 / 远端主动删除(DELETE /rest/thread/delete_thread_by_entry_uuid 的下游表现) |
EntryDeletedError,EntryExpiredError 的子类(pplx_export/core/errors.py:30) |
deleted |
对归档意味着什么:
- 两种状态都永不重试——增量同步不会,加
--force也不会。终态标记存在<out>/index/batch_state.json。 - 工具绝不删除或移动本地归档——仓库副本即备份。导出命令登记终态后优雅退出
(
pplx_export/commands/export_cmd.py:51)。 - 子类关系是刻意设计:只认识
EntryExpiredError的既有路径仍会把ENTRY_DELETED当终态处理;感知子类的路径(batch / export / sync-deleted / search-mode-backfill) 则精确归类为deleted。 - 实践要点:及时导出。过了约 3 个月的清除期,产物 / 报告源链接也不可恢复地过期。
无法下载的资产(toolu_ 句柄)¶
问题:assets/assets_manifest.json 中部分条目的版本被标记
"no_download_channel": true,且 assets/files/ 下没有对应文件。
原因:toolu_ 前缀的 cloud-workspace 句柄(无 URL 形态的 DOC_FILE /
CODE_FILE / UNKNOWN)没有 API 下载通道:GET /rest/assets/<asset_uuid>/data 对它们返回 404
ASSET_NOT_FOUND,file-repository/download 拒绝 file:repo/... 句柄(400)。
这是已知的归档完整性边界,不是导出缺陷。pplx-export assets-backfill 会把这些
版本标记为 no_download_channel 并跳过
(pplx_export/commands/assets_backfill_cmd.py:356)。
修复:
- 目前无可下载——该标记即对此边界的有意记录。
- 内容往往有内联留存:子代理的页面抽取文本与步骤负载保存在线程的 raw JSON
(
raw_entries.json/raw_blocks.json)和渲染出的turns/里——先查那里。 file-repository/list-files已被跟踪为潜在的未来救援路径,见 API 发现路线图。
manifest 布局:归档布局。
日志在哪里?¶
控制台:默认 INFO 级进度;-v / --verbose 切到 DEBUG(请求追踪、内部判定);
warning 与 error 始终显示。
文件:传 --log-file 落盘全量 DEBUG 流(pplx_export/core/logging.py:45):
--log-file不带值时落<out>/index/logs/<cmd>-<timestamp>.log(pplx_export/commands/common.py:218)—— 例如pplx-ask-ask-20260723-120000.log。--log-file PATH写到指定路径。
其他有助于诊断的状态文件(均在 <out>/index/ 下):
| 文件 | 内容 |
|---|---|
.cookies.json |
cookie 缓存(12 小时新鲜期;0o600 原子写入——属登录等价凭证,注意保密) |
batch_state.json |
逐线程导出状态,含 expired / deleted 终态标记 |
answer_variants_log.jsonl |
答案重写变体登记处 |
library_*.json |
各账户的 library 索引快照 |
参见¶
- 快速上手 —— 首次设置与 cookie 导入
- 配置 —— 账户、BOT 空间、降级模式
- pplx-ask —— 交互式查询 CLI
- pplx-export —— 归档 CLI
- 限流 —— 节奏与退避纪律