siyuan-note/siyuan · error
conditional replacement of encrypted documents is not…
Error message
conditional replacement of encrypted documents is not supported
What it means
WriteTreeIfUnchanged performs a compare-and-swap style atomic replacement: it writes only if the file still matches the scanned original bytes. Encrypted .sy files are ciphertext produced by a separate envelope pipeline, so a byte-level conditional replacement is deliberately unsupported — the function returns this error instead of risking ciphertext/AAD inconsistency.
Solutions
- For encrypted notebooks use filesys.WriteTree instead, which goes through the encrypted write pipeline.
- Gate the caller: check the notebook's encryption status before choosing WriteTreeIfUnchanged.
- If atomicity is required, implement concurrency control at a higher level (e.g. serialize via transactions) rather than byte-compare.
Example fix
// before
n, err := filesys.WriteTreeIfUnchanged(tree, original)
// after
if isEncryptedBox(tree.Box) {
err = filesys.WriteTree(tree)
} else {
_, err = filesys.WriteTreeIfUnchanged(tree, original)
} Defensive patterns
Strategy: fallback
Validate before calling
// Go: check encryption before choosing the write path _, encrypted, release, err := acquireCryptoLease(box) // if encrypted, skip WriteTreeIfUnchanged entirely
Try / catch
n, err := filesys.WriteTreeIfUnchanged(tree, original)
if err != nil && err.Error() == "conditional replacement of encrypted documents is not supported" {
err = filesys.WriteTree(tree) // fall back to plain write
} Prevention
- Branch on notebook encryption status before bulk writes
- Use WriteTree for encrypted boxes as the default in batch tooling
- Test batch features against encrypted notebooks, not only plain ones
When it happens
Trigger: Calling filesys.WriteTreeIfUnchanged with a tree whose Box is an encrypted notebook (acquireCryptoLease reports encrypted=true). Callers such as batch apply operations hit this for every doc in an encrypted box.
Common situations: Batch refactoring/bulk-update tooling that uses the conditional write API against an encrypted notebook, assuming parity with plain notebooks.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Conf.Language(393)
- encrypted resources are not supported
- 26
- Access to encrypted notebook data is not supported via this…
- accessing assets in encrypted notebook
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/ef7696f43c6ba2d7.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/filesys/tree_compare_write.go:23
package filesys
import (
"errors"
"github.com/88250/lute/parse"
"github.com/siyuan-note/siyuan/kernel/cache"
"github.com/siyuan-note/siyuan/kernel/util"
)
// WriteTreeIfUnchanged 仅在普通文档仍与扫描源一致时原子替换,防止批量操作覆盖并发修改。
func WriteTreeIfUnchanged(tree *parse.Tree, original []byte) (uint64, error) {
_, encrypted, release, err := acquireCryptoLease(tree.Box)
if err != nil {
return 0, err
}
defer release()
if encrypted {
return 0, errors.New("conditional replacement of encrypted documents is not supported")
}
data, filePath, err := prepareWriteTree(tree)
if err != nil {
return 0, err
}
if err = util.WriteFileIfUnchanged(filePath, original, data); err != nil {
return 0, err
}
cache.SetTreeDataInBox(tree.ID, tree.Box, data)
afterWriteTree(tree)
return uint64(len(data)), nil
}
View on GitHub (pinned to 9f775e8a12)