{"record":{"id":"d07519c795c7768d","repo":"siyuan-note/siyuan","slug":"panic-err","errorCode":null,"errorMessage":"panic(err)","messagePattern":"panic\\(err\\)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/harmony/kernel.go","lineNumber":247,"sourceCode":"\treturn C.CString(util.FilterUploadFileName(C.GoString(name)))\n}\n\n//export AssetName\nfunc AssetName(name *C.char) *C.char {\n\treturn C.CString(util.AssetName(C.GoString(name), ast.NewNodeID()))\n}\n\n//export HTML2Markdown\nfunc HTML2Markdown(html *C.char) *C.char {\n\treturn C.CString(util.NewLute().HTML2Md(C.GoString(html)))\n}\n\n//export Unzip\nfunc Unzip(zipFilePath, destination *C.char) {\n\tvar zipPath string = C.GoString(zipFilePath)\n\tif err := gulu.Zip.Unzip(zipPath, C.GoString(destination)); nil != err {\n\t\tlogging.LogErrorf(\"unzip [%s] failed: %s\", zipPath, err)\n\t\tpanic(err)\n\t}\n}\n\n//export GetExportFilePath\nfunc GetExportFilePath(exportPath *C.char) *C.char {\n\tpathStr := C.GoString(exportPath)\n\tvar absPath string\n\tif strings.HasPrefix(pathStr, \"/export/\") {\n\t\tfileName := strings.TrimPrefix(pathStr, \"/export/\")\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]\", pathStr, fileName)\n\t\t\treturn nil\n\t\t}\n\t\t// 加密导出需要持有覆盖原生复制过程的租约，旧路径解析接口不再返回其明文地址。","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/harmony/kernel.go#L229-L265","documentation":"The gomobile-exported Unzip binding panics when gulu.Zip.Unzip fails to extract an archive. On mobile, panics crossing the JNI/ObjC bridge surface as crashes of the host app; the error is logged first, then re-raised with panic(err). It means the zip file could not be opened or extracted (missing file, corrupt archive, bad destination path, or insufficient space/permissions).","triggerScenarios":"Calling the exported Unzip(zipFilePath, destination) from Android/iOS/HarmonyOS bindings with a nonexistent or unreadable zip path, a corrupted archive, an unwritable destination, or a destination path that already blocks extraction.","commonSituations":"Importing a .sy.zip or asset package where the download was incomplete; requesting extraction into a path without write permission; storage full on device; passing a relative path instead of an absolute one.","solutions":["Check the kernel log for 'unzip [...] failed' to see the underlying cause (open error, crc, mkdir failure).","Verify the zip file exists and is fully downloaded (compare file size/checksum) before calling Unzip.","Pass absolute paths for both zipFilePath and destination and ensure the destination directory exists and is writable.","On the native side, wrap the binding call so a panic does not crash the app; pre-validate inputs instead of relying on the binding.","Free device storage if the error indicates write failures."],"exampleFix":"// before: calling with an unverified path\nbridge.Unzip(zipPath, destDir) // panics if zip is corrupt\n// after: validate on the native side first\nif (!fileExists(zipPath)) throw new Error(\"zip file missing: \" + zipPath);\ntry { bridge.Unzip(zipPath, destDir); } catch (e) { showError(\"unzip failed: \" + e); }","handlingStrategy":"try-catch","validationCode":"if (!fs.existsSync(zipPath)) throw new Error(\"zip missing: \" + zipPath);\nif (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });\nif (fs.statSync(zipPath).size === 0) throw new Error(\"zip is empty: \" + zipPath);","typeGuard":null,"tryCatchPattern":"try {\n  window.siyuan.bridge.Unzip(zipPath, destDir);\n} catch (e) {\n  console.error(\"unzip failed:\", e); // binding panicked; do not let it crash the app\n  showDialog({ content: \"Unzip failed, check the archive and destination path\" });\n}","preventionTips":["Verify download completeness (size/checksum) before unzipping imported packages.","Always pass absolute paths for both zip and destination.","Create the destination directory and check write permission before the call.","Wrap gomobile binding calls in try/catch on the native side since errors arrive as panics."],"tags":["zip","mobile","gomobile","panic"],"backgroundTag":"file-read-failed","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}