{"record":{"id":"97253987903676ba","repo":"siyuan-note/siyuan","slug":"exporting-symbolic-links-is-not-supported","errorCode":null,"errorMessage":"exporting symbolic links is not supported","messagePattern":"exporting symbolic links is not supported","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/export.go","lineNumber":939,"sourceCode":"\t}\n\n\texportFilePath = path.Join(\"temp\", \"export\")\n\tif encryptedBoxID != \"\" {\n\t\texportFilePath = path.Join(\"temp\", \"export\", registerManagedEncryptedExport(encryptedBoxID, \"resources\", zipFilePath))\n\t} else {\n\t\texportFilePath = path.Join(exportFilePath, filepath.Base(zipFilePath))\n\t}\n\treturn\n}\n\n// copyExportResource 复制导出资源，目录逐文件处理以避免将加密资源作为普通文件读取。\nfunc copyExportResource(source, destination string) error {\n\tinfo, err := os.Lstat(source)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif info.Mode()&os.ModeSymlink != 0 {\n\t\treturn errors.New(\"exporting symbolic links is not supported\")\n\t}\n\tif !info.IsDir() {\n\t\treturn copyExportFile(source, destination)\n\t}\n\n\treturn filepath.WalkDir(source, func(current string, entry fs.DirEntry, walkErr error) error {\n\t\tif walkErr != nil {\n\t\t\treturn walkErr\n\t\t}\n\t\tif entry.Type()&os.ModeSymlink != 0 {\n\t\t\treturn errors.New(\"exporting symbolic links is not supported\")\n\t\t}\n\t\trelativePath, relErr := filepath.Rel(source, current)\n\t\tif relErr != nil {\n\t\t\treturn relErr\n\t\t}\n\t\ttarget := filepath.Join(destination, relativePath)\n\t\tif entry.IsDir() {","sourceCodeStart":921,"sourceCodeEnd":957,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/export.go#L921-L957","documentation":"copyExportResource refuses to export a top-level source that is itself a symbolic link, detected via os.Lstat mode. SiYuan rejects symlinks in resource exports to avoid leaking files outside the workspace and to keep exports self-contained.","triggerScenarios":"ExportResources called on a resource path (file or folder) that is a symlink, e.g. assets linked to an external directory.","commonSituations":"Users replacing asset files with links to save space (common with cloud-drive folders, macOS alias-style setups, or ln -s into shared libraries).","solutions":["Replace the symlink with a real copy of the target file/folder before exporting","Exclude symlinked resources from the export selection","Re-sync or re-import the asset as a regular file into the workspace"],"exampleFix":"// before (fails)\nln -s /external/library.png assets/library.png\n// after\ncp -L assets/library.png /tmp/library.png && mv /tmp/library.png assets/library.png","handlingStrategy":"validation","validationCode":"info, err := os.Lstat(path)\nif err == nil && info.Mode()&os.ModeSymlink != 0 { return errors.New(\"resource is a symlink; copy it first\") }","typeGuard":"func isSymlink(path string) bool {\n    info, err := os.Lstat(path)\n    return err == nil && info.Mode()&os.ModeSymlink != 0\n}","tryCatchPattern":"if _, err := model.ExportResources(paths); err != nil {\n    // replace symlinks with real copies, then retry\n}","preventionTips":["Never store assets as symlinks in the workspace","Use cp -L style dereferencing when importing external files","Detect symlinks during asset ingestion and copy content instead"],"tags":["symlink","export","unsupported-operation"],"backgroundTag":"unsupported-operation","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"}