Skip to content

[BUG] 移动云盘访问子目录出现根目录套娃情况 #112

Closed

Description

@MoForgt

请确认以下事项

  • 我确认描述清晰有礼貌,已提供必要诊断信息,在最新版本上可以复现。
  • 我确认已经查过相关文档和已有问题和讨论,本次反馈并非是重复提问。
  • 我确认这是Worker项目问题,并非网络和操作导致,也不是Go版的问题。
  • 我确认已阅读开源许可/免责条款/使用政策,理解使用的风险自行承担。

版本(必填)

https://github.com/OpenListTeam/OpenList-Worker/tree/bfb963eeb8d5324b78d4311c22bbb5e67c657342

平台(必填)

Tencent EdgeOne Makers

DB_FORMAT(必填)

map(整对象 JSON)

DB_DRIVER(必填)

blob

存储驱动(必填)

blob

问题描述(必填)

复现步骤:存储为移动云盘的时候,当访问比如/手机软件的时候按逻辑应该出现的是/手机软件文件夹下的文件。而现在的问题是会出现根目录下的所有文件夹。并且有时候点击/手机文件/阅读.apk的时候会出现/手机软件/阅读.apk/阅读.apk这样套娃的情况。
报错信息:正常的情况下的/api/fs/list这个api提交的是{"path":"/手机软件","password":"","page":1,"per_page":20,"refresh":false}返回的应该是{
"code": 200,
"message": "success",
"data": {
"content": [
{
"name": "阅读.apk",
"size": 20485008,
"is_dir": false,
"created": "2026-10-04T19:47:40.056+08:00",
"modified": "2026-10-04T19:47:40.056+08:00",
"sign": "",
"thumb": "",
"type": 0,
"hashinfo": "",
"hash_info": {}
}
],
"total": 1,
"readme": "",
"header": "",
"write": false,
"write_content_bypass": false,
"provider": "139Yun",
"direct_upload_tools": [],
"page_size": 20,
"cache_expiration": 30
}
},但是现在的问题是会出现返回{
"code": 200,
"message": "success",
"data": {
"content": [
{
"name": "手机软件",
"size": 0,
"is_dir": true,
"created": "2026-10-04T19:47:40.056+08:00",
"modified": "2026-10-04T19:47:40.056+08:00",
"sign": "",
"thumb": "",
"type": 1,
"hashinfo": "",
"hash_info": {}
},
{
"name": "电脑软件",
"size": 0,
"is_dir": true,
"created": "2026-10-04T19:47:31.234+08:00",
"modified": "2026-10-04T19:47:31.234+08:00",
"sign": "",
"thumb": "",
"type": 1,
"hashinfo": "",
"hash_info": {}
},
{
"name": "系统相关",
"size": 0,
"is_dir": true,
"created": "2026-10-04T19:57:26.263+08:00",
"modified": "2026-10-04T19:57:26.263+08:00",
"sign": "",
"thumb": "",
"type": 1,
"hashinfo": "",
"hash_info": {}
},
{
"name": "自写软件",
"size": 0,
"is_dir": true,
"created": "2026-10-04T19:46:55.353+08:00",
"modified": "2026-10-04T19:46:55.353+08:00",
"sign": "",
"thumb": "",
"type": 1,
"hashinfo": "",
"hash_info": {}
}
],
"total": 4,
"write": false,
"write_content_bypass": false,
"provider": "139Yun",
"direct_upload_tools": [],
"cache_expiration": 30
}
}这样的情况。

报错信息(必填)

页面无任何报错。
eopages无法看到函数日志。
不知道是不是根据#95 的Alumos修复了eopages无法部署的问题导致的路由出错。

相关配置(必填)

DB_FORMAT = map
DB_DRIVER = blob
JWT_SECRET = 12345678

复现链接(可选)

Image Image Image Image

Activity

  1. wumingzhinu commented on Oct 8, 2026

    @wumingzhinu
    Contributor

    那你只能等,因为开发大多数是学生,我提交pr都没通过

  2. MoForgt commented on Oct 10, 2026

    @MoForgt
    Author

    2026年10月10日12:33:24为止,用最新的仓库部署,bug仍然存在,说明不是我用ai修复eo无法部署后出现的bug。

  3. changed the title [-][BUG] api返回错误[/-] [+][BUG] 移动云盘访问子目录出现根目录套娃情况[/+] on Oct 11, 2026
  4. PIKACHUIM commented on Oct 11, 2026

    @PIKACHUIM
    Member

    您好,感谢您的反馈,正在定位问题中,似乎和缓存有点关系

  5. PIKACHUIM commented on Oct 13, 2026

    @PIKACHUIM
    Member

    能复现但是定位不到原因,等别的佬看看了

  6. PIKACHUIM commented on Oct 15, 2026

    @PIKACHUIM
    Member

    感谢您的反馈,和eo缓存应该没关系,也并非139云盘独有,但是具体原因还是没定位到...

  7. 3 remaining items

  8. wumingzhinu commented on Oct 20, 2026

    @wumingzhinu
    Contributor

    17. @wumingzhinu 我现在的仓库https://github.com/MoForgt/OpenList-Worker 还是和你https://github.com/wumingzhinu/OpenList-Worker/tree/fix/139-subdir-listing 完全一模一样呢,要不你fork一下我这个仓库重新部署一下,或者你看下https://pan.xrbk.cn 问题还是存在啊,要不你发我一下你的网站地址我去看看。

    有点稀奇,我还是直接同步最新的worker部署没有问题

  9. wumingzhinu commented on Oct 20, 2026

    @wumingzhinu
    Contributor

    18. 而且出现了新的问题,网页提示139 Cloud token is near expiry; configure user_domain_id to use the PC refreshToken API,我更换了授权,依然还是提示这个。不知道是不是移动云盘那边更换了接口

    不对啊,我刚部署,可以用移动网盘啊

  10. MoForgt commented on Oct 20, 2026

    @MoForgt
    Author

    这个bug很神奇

  11. wumingzhinu commented on Oct 20, 2026

    @wumingzhinu
    Contributor

    分析结论更新(基于 issue 内四张截图 + 版本比对)

    一、已经定案的部分

    1. 前端无罪。 载荷截图显示请求体 path: "/手机软件" 是正确的——前端没有发错路径。

    2. 后端实锤。 响应截图显示 path=/手机软件 返回了 200,但 content 是根目录的 4 个文件夹(手机软件/电脑软件/系统相关/自写软件)。path 对了、内容错了,问题在后端链路。

    3. 套娃机制。 驱动按路径逐段"按名找目录",找到"手机软件"、拿到一个看起来非空的 id,然后拿这个 id 去调 139 的 /file/list。关键在最后一步:139 接口对它不认的 parentFileId 不报错,而是静默返回根目录内容。于是整个链路 200 成功、无任何异常,页面上就是"子目录显示根目录内容"→ 再点进去 → /手机软件/手机软件 → 无限套娃。

    4. 版本核查(重要)。 报告者基准版(bfb963e,10-08)与当前最新 main 之间,139 驱动的列表代码零变化(只有 #116 token 刷新,与列表无关),resolveCatalogId 的静默回退逻辑至今仍在 main 里原样存在。所以"最新版部署未复现"不代表已修复——最新版多了 #75 目录缓存,正确列表一旦被缓存,偶发的错误回源就被掩盖了;能不能踩中取决于账号数据/路由结果,不是版本。

    二、还差最后一层:那个"存在但无效"的 id 是怎么来的

    只剩三个嫌疑环节,需要一次带日志的复现才能区分:

    1. 路由 host 不对——qryRoutePolicy 返回成功,但给的个人云域名上的接口不认 parentFileId
    2. id 字段认错了——139 返回里文件夹的可列 id 换了字段名,程序拿到的"fileId"是个废值
    3. 账号空间不匹配——type 留空默认按新版个人云走;若账号实际是老版空间/家庭云,接口各说各话

    三、给 @MoForgt 的两个零成本实验

    1. 新建文件夹测试:在 139 官方 App 里新建一个文件夹、放个文件,从网站点进去——
      • 新文件夹也套娃 → 倾向嫌疑 1/3(路由或账号空间问题),请顺便确认后台存储的 type 设置与 App 里看到的云类型(新版个人云/家庭云)一致
      • 只有老文件夹套娃 → 倾向嫌疑 2(老数据缺字段)
    2. 如果方便,后台管理页截一下这个 139 存储的状态栏和配置(隐去 authorization)。

    四、后续

    • 我可以出一个诊断分支(只加几行日志:列目录时打印用了哪个 host、parentFileId 是什么、返回几条,不动任何逻辑),@MoForgt 部署后在 EdgeOne 后台看函数日志,一次复现就能区分上面三个嫌疑。需要的话我发出来。
    • 无论最终根因是哪个,fix(139): 子目录列表静默回退根目录与文件路径套娃 #126 仍建议合并:它把"找不到/无效 id/路由失败"从静默回退改成显式报错——这次要不是报警器恰好都没覆盖到最后一步,定位不会拖这么久。
    • 另:@MoForgt 提到的 "token is near expiry" 提示来自 feat(139): refresh expiring cloud tokens via PC API #116——授权里解析出的有效期距今 ≤15 天且未配 user_domain_id 就会提示;配上 user_domain_id 即可走 PC 接口自动续期。
  12. MoForgt commented on Oct 20, 2026

    @MoForgt
    Author

    Image 你好,这是我的配置,并且没有看到关于user_domain_id的配置

    Image 这是首页返回的

  13. MoForgt commented on Oct 20, 2026

    @MoForgt
    Author

    Image这个是移动云盘网页版内的信息

    Image这是app内的信息

  14. nike64542-byte commented on Oct 20, 2026

    @nike64542-byte
    Contributor

    根因定位:EdgeOne 平台间歇性丢失请求体 + 三层容错缺陷,把"偶发故障"变成"显示根目录"

    先说结论:139Yun 驱动和 139 接口本身没有问题(直连 139 API 验证:非法 parentFileId 返回明确错误码 04000002/04000010,不会静默返回根目录;mcloud-sign 签名错误也不校验,与签名/时区无关)。这个 bug 是一个平台缺陷 + 三层代码容错设计缺陷叠加的结果,任何一层做对,bug 都不会以现在这个形态出现。

    第 1 层:EdgeOne Functions 间歇性丢失/无法读取 POST 请求体(平台缺陷,触发源)

    用同样合法的 JSON(路径唯一、避开缓存、Content-Type: application/json)对 /api/fs/list 做探针测试:

    • EdgeOne 站点 A:30 次中 2 次服务端解析出的结果与"发送损坏 JSON"的响应完全一致(即 body 解析失败),1 次出网直接 fetch failed
    • EdgeOne 站点 B:10 次中 4 次 c.req.text() 读取 body 时直接抛异常
    • 串行 3/10 vs 10 路并发 3/10 —— 错误率与浏览器并发/连接复用无关
    • 同代码部署到 Cloudflare:0 失败

    即 EdgeOne 的 Node 云函数在收到请求时 body 已经被平台弄丢/截断,概率随部署节点在 ~7%~40% 波动。函数侧无法进一步确认平台内部机制(EdgeOne Pages 面板无函数日志可用),需要 EdgeOne 官方函日志才能定论,但"平台丢 body"这一现象可以稳定复现。

    第 2 层:c.req.json().catch(() => ({})) 把事故静默降级为"请求根目录"(关键放大器)

    src/backend/server/fs.ts 绝大多数 handler 都是同一模式:

    const body = await c.req.json().catch(() => ({}))    // body 丢失/解析失败 → {}
    const reqPath = getActualPath(user, body.path || "/") // path 缺失 → 默认 "/"

    于是"平台丢 body"被吞掉后变成 path = "/" → 返回根目录列表,HTTP 200,页面无任何报错。同时解释了两个现象:

    • 为什么只在 EdgeOne 复现、Cloudflare 正常:只有 EO 会丢 body
    • 为什么无任何报错、时好时坏、刷新有时恢复:下一次请求 body 正常就恢复,但这次会看到错误内容

    第 3 层:139 驱动 resolveCatalogId 找不到目录时 break 静默回退(套娃放大器)

    src/backend/drivers/139/driver.ts:47-55 逐段按名字找目录,找不到就 break,返回上层/根 catalogId 继续列目录:

    const foundFolder = disk.folders.find((f) => f.catalogName === part)
    if (foundFolder) { currentCatalogId = foundFolder.catalogID } else { break }

    即使第 2 层没触发(手输错误路径、挂载点变更等),错误路径也会"成功"列出上层目录,比如访问 /手机软件/手机软件 返回 手机软件 的真实内容,形成截图里的套娃。PR #121 针对的就是这里。

    第 4 层:文件树缓存把瞬时故障固化为 30 分钟,用户无法自救

    错误的根目录列表会被写入文件树缓存(ft:{storageId}:{path},TTL 默认 30 分钟);实测站点缓存里就存在错误内容,清空缓存后立即恢复。而前端传的 refresh 参数后端完全没有实现(全仓库无任何读取),用户点"刷新"无法击穿缓存,只能等 TTL 过期。

    复现要点

    EdgeOne 部署 + 139 存储(挂载点/根目录随意)→ 高频点击子目录 → 一定概率显示根目录内容且无报错;刷新大概率恢复;/手机软件/手机软件 式套娃在缓存内持续 30 分钟。多轮探针 + 损坏 JSON 对照实验可以稳定区分"平台丢 body"与"正常解析"两种分支。

  15. wumingzhinu commented on Oct 20, 2026

    @wumingzhinu
    Contributor

    24. Image这个是移动云盘网页版内的信息
    Image这是app内的信息

    我用小号申请了github action ,完成了修复,但是老是failed to read request body,未能解决

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions