{"record":{"id":"0bf99ac08cb91838","repo":"siyuan-note/siyuan","slug":"exporting-resources-across-encrypted-notebook-boun","errorCode":null,"errorMessage":"exporting resources across encrypted notebook boundaries is not supported","messagePattern":"exporting resources across encrypted notebook boundaries is not supported","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/export.go","lineNumber":1018,"sourceCode":"\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 {\n\t\t\treturn nil\n\t\t}\n\n\t\ttree := prepareExportTree(bt)\n\t\tif numberErr := applyHeadingNumbersForExport(tree, bt, false); nil != numberErr {","sourceCodeStart":1000,"sourceCodeEnd":1036,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/model/export.go#L1000-L1036","documentation":"The exporter allows batching resources from one encrypted notebook, but resources must not come from two different encrypted notebooks in a single export. Once an encrypted boxID is recorded, any subsequent resource from a different encrypted box aborts the export, since each encrypted box requires its own decryption context.","triggerScenarios":"ExportResources called with asset paths from two different encrypted notebooks in the same call (boxID extracted from the second path differs from the first).","commonSituations":"UI multi-select export across notebooks where more than one selected notebook is encrypted; plugin aggregating assets from several encrypted notebooks into one request.","solutions":["Split the export into one ExportResources call per encrypted notebook","Group requested resources by boxID before calling ExportResources","Mix encrypted resources with normal-notebook resources is also rejected — keep batches homogeneous"],"exampleFix":"// before\nExportResources([]string{\"boxA/assets/a.png\", \"boxB/assets/b.png\"}) // both encrypted\n// after\nExportResources([]string{\"boxA/assets/a.png\"})\nExportResources([]string{\"boxB/assets/b.png\"})","handlingStrategy":"validation","validationCode":"function groupByBox(paths) {\n  const groups = {};\n  for (const p of paths) {\n    const box = p.split('/')[0];\n    (groups[box] = groups[box] || []).push(p);\n  }\n  return Object.values(groups); // one ExportResources call per group\n}","typeGuard":null,"tryCatchPattern":"try { await exportResources(paths); }\ncatch (e) {\n  if (String(e).includes('across encrypted notebook boundaries')) {\n    for (const g of groupByBox(paths)) await exportResources(g);\n  }\n}","preventionTips":["Never batch resources from multiple encrypted notebooks in one call","Group export requests by notebook ID before invoking the API","Keep UI multi-select exports scoped per notebook when encryption is involved"],"tags":["export","encrypted-notebook","batching"],"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"}