Please confirm the following
OpenList Version (required)
v4.2.1
Storage Driver Used (required)
115_open
Bug Description (required)
问题描述
在 115 网盘(Open API 驱动)上连续执行 Copy → Rename 操作时,有一定概率出现重命名了源文件而非复制后的目标文件的问题。同时 POST /api/fs/mkdir 在 115 路径下创建文件夹也会失败。
环境信息
- 驱动类型:115_open(Open API 令牌登录)
- 挂载路径:
/115
问题一:Copy → Rename 误操作源文件
复现步骤
- 对
/115/整理/待验/二次元/文件A 执行 Copy 到 /115/整理/待验/二次元/已验/
- Copy 成功后立即对
/115/整理/待验/二次元/已验/文件A 执行 Rename
- 有时重命名的是源文件
/115/整理/待验/二次元/文件A 而非复制后的文件
根因
drivers/115_open/driver.go 的 Copy 方法(第 247 行)调用 115 Open API 复制文件后,API 不返回新文件的信息,驱动返回的是源文件对象(包含源文件的 Fid)。
在 internal/op/fs.go 的 Copy 缓存更新逻辑中(第 551-559 行),CopyResult 返回非 nil 对象时不会打 Temp 标记,导致目标目录缓存里存入了源文件的 Fid 而非新复制文件的 Fid。
后续 Rename 操作在 internal/op/fs.go 第 456 行通过 Get(..., excludeTempObj=true) 查找源文件,由于缓存条目没有 Temp 标记,excludeTempObj 保护失效,直接命中了带源文件 Fid 的缓存条目,最终通过该 Fid 调用 Rename API,错误地重命名了源文件。
影响范围
- CopyResult 接口的实现驱动中,返回源对象而非新对象的驱动均受影响
- Move 操作存在同类风险
问题二:Mkdir 失败(GetFolderInfo 反序列化错误)
复现步骤
curl 'http://127.0.0.1:5244/api/fs/mkdir' \
-H 'Content-Type: application/json;charset=UTF-8' \
--data-raw '{"path":"/115/整理/待验/二次元/电影"}'
返回:
{"code":500,"message":"failed to check if dir exists: failed to get obj: json: cannot unmarshal array into Go value of type sdk.GetFolderInfoResp"}
根因
115 Open API 的 folder/get_info 接口返回 data 字段的格式从单个对象 {...} 变更为 JSON 数组 [{...}]。但 SDK(115-sdk-go v0.2.3)的 GetFolderInfoResp 类型仍是单一结构体,导致 json.Unmarshal 失败。
SDK 中已有 json_types/StructOrArray[T] 类型可以处理这种场景,但 GetFolderInfoByPath 方法未使用。
Mkdir 在 op.MakeDir 中会先调用 Get 检查目录是否存在,Get 调用驱动的 GetFolderInfoByPath → SDK 解析失败 → 错误向上传播。
Logs (required)
问题一
2026-05-24 18:05:09 failed make dir /115/整理/待验/二次元/剧集:
json: cannot unmarshal array into Go value of type sdk.GetFolderInfoResp
2026-05-24 18:07:22 failed make dir /115/整理/待验/二次元/电影:
json: cannot unmarshal array into Go value of type sdk.GetFolderInfoResp
问题二:Mkdir 失败
2026-05-25 09:28:43 failed rename
百合熊风暴 - S01E05 - 第 05 集.cht.ass
→ 百合熊风暴 (2015) S01E05 想要独占你.ass:
code: 20004, message: 很抱歉,该目录名称已存在。
Configuration File Content (required)
{
"force": false,
"site_url": "",
"cdn": "",
"jwt_secret": "UtUClEwpuZhhi10Y",
"token_expires_in": 48,
"database": {
"type": "sqlite3",
"host": "",
"port": 0,
"user": "",
"password": "",
"name": "",
"db_file": "data/data.db",
"table_prefix": "x_",
"ssl_mode": "",
"dsn": ""
},
"meilisearch": {
"host": "http://localhost:7700",
"api_key": "",
"index": "openlist"
},
"scheme": {
"address": "0.0.0.0",
"http_port": 5244,
"https_port": -1,
"force_https": false,
"cert_file": "",
"key_file": "",
"unix_file": "",
"unix_file_perm": "",
"enable_h2c": false,
"enable_h3": false
},
"temp_dir": "data/temp",
"bleve_dir": "data/bleve",
"dist_dir": "",
"log": {
"enable": true,
"name": "data/log/log.log",
"max_size": 50,
"max_backups": 30,
"max_age": 28,
"compress": false
},
"delayed_start": 0,
"auto_memory_limit": 4,
"min_free_memory": 0,
"max_block_limit": 0,
"max_connections": 0,
"max_concurrency": 64,
"tls_insecure_skip_verify": false,
"tasks": {
"download": { "workers": 5, "max_retry": 1 },
"transfer": { "workers": 5, "max_retry": 2 },
"upload": { "workers": 5, "max_retry": 0 },
"copy": { "workers": 5, "max_retry": 2 },
"move": { "workers": 5, "max_retry": 2 },
"decompress": { "workers": 5, "max_retry": 2 },
"decompress_upload": { "workers": 5, "max_retry": 2 },
"allow_retry_canceled": false
},
"cors": {
"allow_origins": ["*"],
"allow_methods": ["*"],
"allow_headers": ["*"]
},
"s3": { "enable": false, "port": 5246, "ssl": false },
"ftp": { "enable": false, "listen": ":5221" },
"sftp": { "enable": false, "listen": ":5222" },
"last_launched_version": "v4.2.1",
"proxy_address": ""
}
Reproduction Link (optional)
No response
Please confirm the following
I have read and agree to AGPL-3.0 Section 15 .
The program is provided "as is" without any warranties; you bear all risks of using it.
I have read and agree to AGPL-3.0 Section 16 .
The copyright holders and distributors are not liable for any damages resulting from the use or inability to use the program.
I confirm my description is clear, polite, helps developers quickly locate the issue, and complies with community rules.
I have read the OpenList documentation.
I confirm there are no duplicate issues or discussions.
I confirm this is an
OpenListissue, not caused by other reasons (such as network, dependencies, or operation).I believe this issue must be handled by
OpenListand not by a third party.I confirm this issue is not fixed in the latest version.
I have not read these checkboxes and therefore I just ticked them all, Please close this issue.
OpenList Version (required)
v4.2.1
Storage Driver Used (required)
115_open
Bug Description (required)
问题描述
在 115 网盘(Open API 驱动)上连续执行 Copy → Rename 操作时,有一定概率出现重命名了源文件而非复制后的目标文件的问题。同时
POST /api/fs/mkdir在 115 路径下创建文件夹也会失败。环境信息
/115问题一:Copy → Rename 误操作源文件
复现步骤
/115/整理/待验/二次元/文件A执行 Copy 到/115/整理/待验/二次元/已验//115/整理/待验/二次元/已验/文件A执行 Rename/115/整理/待验/二次元/文件A而非复制后的文件根因
drivers/115_open/driver.go的Copy方法(第 247 行)调用 115 Open API 复制文件后,API 不返回新文件的信息,驱动返回的是源文件对象(包含源文件的 Fid)。在
internal/op/fs.go的Copy缓存更新逻辑中(第 551-559 行),CopyResult返回非 nil 对象时不会打 Temp 标记,导致目标目录缓存里存入了源文件的 Fid 而非新复制文件的 Fid。后续 Rename 操作在
internal/op/fs.go第 456 行通过Get(..., excludeTempObj=true)查找源文件,由于缓存条目没有 Temp 标记,excludeTempObj保护失效,直接命中了带源文件 Fid 的缓存条目,最终通过该 Fid 调用 Rename API,错误地重命名了源文件。影响范围
问题二:Mkdir 失败(GetFolderInfo 反序列化错误)
复现步骤
返回:
{"code":500,"message":"failed to check if dir exists: failed to get obj: json: cannot unmarshal array into Go value of type sdk.GetFolderInfoResp"}根因
115 Open API 的 folder/get_info 接口返回 data 字段的格式从单个对象 {...} 变更为 JSON 数组 [{...}]。但 SDK(115-sdk-go v0.2.3)的 GetFolderInfoResp 类型仍是单一结构体,导致 json.Unmarshal 失败。
SDK 中已有 json_types/StructOrArray[T] 类型可以处理这种场景,但 GetFolderInfoByPath 方法未使用。
Mkdir 在 op.MakeDir 中会先调用 Get 检查目录是否存在,Get 调用驱动的 GetFolderInfoByPath → SDK 解析失败 → 错误向上传播。
Logs (required)
问题一
2026-05-24 18:05:09 failed make dir /115/整理/待验/二次元/剧集:
json: cannot unmarshal array into Go value of type sdk.GetFolderInfoResp
2026-05-24 18:07:22 failed make dir /115/整理/待验/二次元/电影:
json: cannot unmarshal array into Go value of type sdk.GetFolderInfoResp
问题二:Mkdir 失败
2026-05-25 09:28:43 failed rename
百合熊风暴 - S01E05 - 第 05 集.cht.ass
→ 百合熊风暴 (2015) S01E05 想要独占你.ass:
code: 20004, message: 很抱歉,该目录名称已存在。
Configuration File Content (required)
{ "force": false, "site_url": "", "cdn": "", "jwt_secret": "UtUClEwpuZhhi10Y", "token_expires_in": 48, "database": { "type": "sqlite3", "host": "", "port": 0, "user": "", "password": "", "name": "", "db_file": "data/data.db", "table_prefix": "x_", "ssl_mode": "", "dsn": "" }, "meilisearch": { "host": "http://localhost:7700", "api_key": "", "index": "openlist" }, "scheme": { "address": "0.0.0.0", "http_port": 5244, "https_port": -1, "force_https": false, "cert_file": "", "key_file": "", "unix_file": "", "unix_file_perm": "", "enable_h2c": false, "enable_h3": false }, "temp_dir": "data/temp", "bleve_dir": "data/bleve", "dist_dir": "", "log": { "enable": true, "name": "data/log/log.log", "max_size": 50, "max_backups": 30, "max_age": 28, "compress": false }, "delayed_start": 0, "auto_memory_limit": 4, "min_free_memory": 0, "max_block_limit": 0, "max_connections": 0, "max_concurrency": 64, "tls_insecure_skip_verify": false, "tasks": { "download": { "workers": 5, "max_retry": 1 }, "transfer": { "workers": 5, "max_retry": 2 }, "upload": { "workers": 5, "max_retry": 0 }, "copy": { "workers": 5, "max_retry": 2 }, "move": { "workers": 5, "max_retry": 2 }, "decompress": { "workers": 5, "max_retry": 2 }, "decompress_upload": { "workers": 5, "max_retry": 2 }, "allow_retry_canceled": false }, "cors": { "allow_origins": ["*"], "allow_methods": ["*"], "allow_headers": ["*"] }, "s3": { "enable": false, "port": 5246, "ssl": false }, "ftp": { "enable": false, "listen": ":5221" }, "sftp": { "enable": false, "listen": ":5222" }, "last_launched_version": "v4.2.1", "proxy_address": "" }Reproduction Link (optional)
No response