{"record":{"id":"a79466e34d42c4cc","repo":"siyuan-note/siyuan","slug":"unzip-s-failed-s","errorCode":null,"errorMessage":"unzip [%s] failed: %s","messagePattern":"unzip \\[(.+?)\\] failed: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"kernel/mobile/kernel.go","lineNumber":381,"sourceCode":"\treturn filepath.Base(path)\n}\n\nfunc FilterUploadFileName(name string) string {\n\treturn util.FilterUploadFileName(name)\n}\n\nfunc AssetName(name string) string {\n\treturn util.AssetName(name, ast.NewNodeID())\n}\n\nfunc HTML2Markdown(html string) string {\n\treturn util.NewLute().HTML2Md(html)\n}\n\nfunc Unzip(zipFilePath, destination string) {\n\tif err := gulu.Zip.Unzip(zipFilePath, destination); nil != err {\n\t\tlogging.LogErrorf(\"unzip [%s] failed: %s\", zipFilePath, err)\n\t\tpanic(err)\n\t}\n}\n\n// GetExportFilePath 解析导出文件绝对路径，绕过 HTTP 层以避免锁屏密码拦截。\n// exportPath 格式为 \"/export/xxx.zip\" 或 \"assets/xxx\"。\n// 返回文件在磁盘上的绝对路径，以便原生端分块拷贝，避免大文件内存溢出。\n// 解析失败返回空字符串。\nfunc GetExportFilePath(exportPath string) (ret string) {\n\tvar absPath string\n\tif after, ok := strings.CutPrefix(exportPath, \"/export/\"); ok {\n\t\tfileName := after\n\t\tif decoded, err := url.PathUnescape(fileName); err == nil {\n\t\t\tfileName = decoded\n\t\t}\n\t\tfileName = filepath.Clean(fileName)\n\t\tif strings.HasPrefix(fileName, \"..\") {\n\t\t\tlogging.LogWarnf(\"get export file path [%s] blocked: path traversal attempt [%s]\", exportPath, fileName)\n\t\t\treturn","sourceCodeStart":363,"sourceCodeEnd":399,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/mobile/kernel.go#L363-L399","documentation":"The mobile gomobile binding Unzip extracts a zip archive via gulu.Zip.Unzip and, on any error, logs it and panics. The panic message reports the source archive path and the underlying unzip error. On mobile, a panic aborts the calling native bridge call.","triggerScenarios":"Calling the exported Unzip(zipFilePath, destination) from native mobile code when the zip is missing, corrupt, password-protected in an unsupported way, or the destination is unwritable.","commonSituations":"Interrupted downloads producing truncated zips, restoring workspace/snapshot archives on Android/iOS, insufficient storage space, destination path not created or permission-restricted by the OS sandbox.","solutions":["Verify the zip file exists and is complete (re-download/re-transfer the archive) before calling Unzip","Ensure the destination directory exists and the app has write permission to it","Check the underlying error text in the log line \"unzip [...] failed: ...\" for the specific cause (e.g. CRC mismatch vs. open failure)","Catch/recover the panic on the native side and surface a user-facing failure instead of crashing","Free up device storage if the error indicates write failure"],"exampleFix":"// before\nUnzip(\"/sdcard/backup.zip\", \"/data/data/app/workspace\") // panics if file truncated\n// after\nif fileExistsAndValid(\"/sdcard/backup.zip\") && dirWritable(\"/data/data/app/workspace\") {\n    Unzip(\"/sdcard/backup.zip\", \"/data/data/app/workspace\")\n} else { showError() }","handlingStrategy":"try-catch","validationCode":"func safeUnzip(zipPath, dest string) (err error) {\n    if _, err = os.Stat(zipPath); err != nil { return fmt.Errorf(\"zip missing: %w\", err) }\n    if err = os.MkdirAll(dest, 0755); err != nil { return fmt.Errorf(\"dest unwritable: %w\", err) }\n    return nil\n}","typeGuard":"null","tryCatchPattern":"// Kotlin/Java side: wrap the binding call\ntry {\n    SiYuanKernel.Unzip(zipPath, dest)\n} catch (e: Throwable) {\n    Log.e(TAG, \"unzip failed\", e)\n    showRestoreFailedDialog()\n}","preventionTips":["Verify archive integrity (size/checksum) after download before unzipping","Pre-create the destination directory and check free disk space","Never rely on Unzip returning — it panics; always guard the native call","Read the paired log line for the underlying cause"],"tags":["zip","mobile","panic","file-extraction"],"backgroundTag":"file-read-failed","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}