{"record":{"id":"99d8e2f12f2dc6db","repo":"siyuan-note/siyuan","slug":"exporting-non-asset-files-from-encrypted-notebooks","errorCode":null,"errorMessage":"exporting non-asset files from encrypted notebooks is not supported","messagePattern":"exporting non-asset files from encrypted notebooks is not supported","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/export.go","lineNumber":1013,"sourceCode":"}\n\n// exportResourcesEncryptedBox 校验资源导出是否跨越加密边界，并返回唯一允许的加密来源 boxID。\nfunc exportResourcesEncryptedBox(resourcePaths []string) (encryptedBoxID string, err error) {\n\thasNormalResource := false\n\tfor _, resourcePath := range resourcePaths {\n\t\tresourceFullPath := filepath.Join(util.WorkspaceDir, resourcePath)\n\t\tif !util.IsAbsPathInWorkspace(resourceFullPath) {\n\t\t\treturn \"\", errors.New(\"resource path [\" + resourcePath + \"] is not in workspace\")\n\t\t}\n\t\tboxID := ExtractBoxIDFromAssetsPath(resourceFullPath)\n\t\tif boxID == \"\" || !IsEncryptedBox(boxID) {\n\t\t\thasNormalResource = true\n\t\t\tcontinue\n\t\t}\n\n\t\tassetsPath := filepath.Join(util.DataDir, boxID, \"assets\")\n\t\tif !gulu.File.IsSubPath(assetsPath, resourceFullPath) {\n\t\t\treturn \"\", errors.New(\"exporting non-asset files from encrypted notebooks is not supported\")\n\t\t}\n\t\tif encryptedBoxID == \"\" {\n\t\t\tencryptedBoxID = boxID\n\t\t} else if encryptedBoxID != boxID {\n\t\t\treturn \"\", errors.New(\"exporting resources across encrypted notebook boundaries is not supported\")\n\t\t}\n\t}\n\tif encryptedBoxID != \"\" && hasNormalResource {\n\t\treturn \"\", errors.New(\"exporting encrypted and normal notebook resources together is not supported\")\n\t}\n\treturn\n}\n\nfunc ExportPreview(id string, fillCSSVar bool, accessChecker ...EmbedBlockAccessChecker) (retStdHTML string) {\n\tif exportErr := withExportReadLockByBlockID(id, func() error {\n\t\tblockRefMode := Conf.Export.BlockRefMode\n\t\tbt := getExportBlockTree(id)\n\t\tif nil == bt {","sourceCodeStart":995,"sourceCodeEnd":1031,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/export.go#L995-L1031","documentation":"In encrypted notebooks the exporter only supports asset files (files under <boxID>/assets/). If a resource path inside an encrypted box resolves outside the assets directory, exportResourcesEncryptedBox rejects it because non-asset files in encrypted boxes cannot be safely read/exported in plaintext form.","triggerScenarios":"ExportResources called with a path inside an encrypted notebook that is not under <boxID>/assets/ (e.g. a .sy document, storage/av database file, or temp file inside the encrypted box).","commonSituations":"Plugin tries to export a database (storage/av) or custom file from an encrypted notebook; a stale/moved resource path now resolves under the box root instead of assets/.","solutions":["Only pass files located in the notebook's assets/ directory when the box is encrypted","Export non-asset encrypted content via the dedicated document/AV export APIs instead of ExportResources","Check IsEncryptedBox(boxID) and reject non-asset paths in the caller beforehand"],"exampleFix":"// before\nExportResources([\"20240101120000-abcdefg/storage/av/20240101-xxx.av\"]) // inside encrypted box\n// after\nExportResources([\"20240101120000-abcdefg/assets/image.png\"])","handlingStrategy":"validation","validationCode":"async function isExportableEncryptedResource(resourcePath) {\n  const boxID = extractBoxIDFromAssetsPath(resourcePath);\n  if (!boxID) return false;\n  const assetsPrefix = boxID + '/assets/';\n  return resourcePath.startsWith(assetsPrefix);\n}","typeGuard":"const isAsset = p => p.split('/').slice(0,2).join('/') === boxID + '/assets';","tryCatchPattern":"try {\n  await exportResources(paths);\n} catch (e) {\n  if (String(e).includes('non-asset files from encrypted notebooks')) {\n    notifyUser('Only assets/ files can be exported from encrypted notebooks');\n  }\n}","preventionTips":["For encrypted boxes only export files under <boxID>/assets/","Use dedicated document/database export APIs for non-asset content","Check notebook encryption status before building export batches"],"tags":["export","encrypted-notebook","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"}