siyuan-note/siyuan · error
Conf.Language(396)
Error message
Conf.Language(396)
What it means
When pinning, UpdatePinnedDocs resolves each ID via treenode.GetBlockTree and refuses to pin documents that live in an encrypted notebook. Instead of a hard-coded message it returns the localized user-facing string Conf.Language(396), which explains that encrypted notebooks do not support this operation. This keeps encrypted-notebook restrictions consistent with other kernel operations.
Solutions
- Move the document to a non-encrypted notebook before pinning it.
- Skip pinning documents whose notebook is encrypted; filter by IsEncryptedBox before calling.
- Handle the localized message in the client UI as an informational restriction rather than retrying.
Example fix
// before
model.UpdatePinnedDocs([]string{docID}, "pin", "", false)
// after
if bt := treenode.GetBlockTree(docID); bt == nil || model.IsEncryptedBox(bt.BoxID) {
return // do not attempt to pin encrypted-notebook docs
}
model.UpdatePinnedDocs([]string{docID}, "pin", "", false) Defensive patterns
Strategy: validation
Validate before calling
bt := treenode.GetBlockTree(docID)
if bt != nil && model.IsEncryptedBox(bt.BoxID) {
return errors.New("refusing to pin document in encrypted notebook")
} Type guard
func isPlainBox(boxID string) bool { return !model.IsEncryptedBox(boxID) } Try / catch
if err := model.UpdatePinnedDocs(ids, "pin", "", false); err != nil {
if err.Error() == model.Conf.Language(396) {
// surface encrypted-notebook restriction to the user
}
} Prevention
- Check IsEncryptedBox on the notebook before any pin operation
- Skip encrypted notebooks when batch-pinning
- Educate users that encrypted notebooks do not support pinned entries
- Keep the localized message (Language key 396) handled as a restriction, not a bug
When it happens
Trigger: Calling UpdatePinnedDocs with action="pin" and an ids entry whose block-tree record points into a notebook where IsEncryptedBox(bt.BoxID) is true (an encrypted notebook). Unpinning skips this check entirely.
Common situations: User or plugin tries to pin a document inside an encrypted notebook via the pin UI, API, or a script; encrypted-notebook content is being manipulated by an external tool that ignores the restriction.
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
- conditional replacement of encrypted attribute views is not…
- Conf.Language(313)
- Conf.Language(313)
- Conf.Language(313)
- Conf.Language(386)
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/a766ff0de9efdad4.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/pinned_docs.go:186
if err != nil {
return err
}
selected := map[string]bool{}
refs := []pinnedDocRef{}
for _, id := range ids {
if !ast.IsNodeIDPattern(id) {
return fmt.Errorf("invalid document ID [%s]", id)
}
if selected[id] {
continue
}
selected[id] = true
if action == "unpin" {
continue
}
bt := treenode.GetBlockTree(id)
if bt != nil && IsEncryptedBox(bt.BoxID) {
return fmt.Errorf("%s", Conf.Language(396))
}
if !isPinnableDocument(bt) {
return fmt.Errorf("document [%s] cannot be pinned", id)
}
box := Conf.Box(bt.BoxID)
if box == nil || box.Stat(bt.Path) == nil {
return fmt.Errorf("document [%s] is unavailable", id)
}
ial := box.docIAL(bt.Path)
if ial == nil {
return fmt.Errorf("cannot read pinned document [%s]", id)
}
if id != bt.BoxID && ial[DocHiddenAttr] == "true" {
return fmt.Errorf("document [%s] cannot be pinned", id)
}
refs = append(refs, pinnedDocRef{ID: id, Notebook: bt.BoxID})
}
if action == "pin" && selected[targetID] {View on GitHub (pinned to 9f775e8a12)