siyuan-note/siyuan · error
invalid .sy base name
Error message
invalid .sy base name [%s]: must end with .sy
What it means
SyObjectBase validates that a relative path names a .sy document file: it extracts the base name and requires the ".sy" suffix (the next check also requires a node-ID stem). This guard feeds SyAAD, which builds the authenticated associated data from the stable file base name, so any non-.sy path is rejected before crypto operations.
Solutions
- Pass only document paths whose base name ends in .sy.
- Strip or fix a wrong extension before calling; convert the source to a .sy document if needed.
- Check the path is a file path, not a directory or asset path.
Example fix
// before
SyObjectBase("20260101120000-abcdefg.json")
// after
SyObjectBase("20260101120000-abcdefg.sy") Defensive patterns
Strategy: validation
Validate before calling
function isSyBase(p) {
const base = p.split(/[\\/]/).pop();
return typeof base === "string" && base.endsWith(".sy");
} Try / catch
if err := filesys.SyObjectBase(relPath); err != nil {
// non-.sy path: route to the correct handler or reject
} Prevention
- Only feed .sy document paths into crypto/AAD APIs.
- Keep asset and history paths on their own code paths.
- Build paths from tree IDs so the extension is always .sy.
When it happens
Trigger: Calling SyObjectBase (directly or via SyAAD) with a relativePath whose base name does not end with .sy, e.g. "20260101120000-abcdefg.json", "assets/foo.png", a directory path, or an empty string.
Common situations: Passing asset files or history snapshots to an API expecting .sy document paths; a path separator bug leaving a directory name as the base; constructing paths programmatically with the wrong extension.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- refuse to write decrypted asset inside workspace
- source is not an encrypted asset
- accessing assets in encrypted notebook
- Argon2id KeyLength must be 32
- Argon2id Memory too low (minimum 64 MB)
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/068182d284d9d70f.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/filesys/crypto_hook.go:112
}()
aad, err := SyAAD(boxID, relativePath)
if err != nil {
return nil, err
}
return util.DecryptWithAAD(fileKey, data, []byte(aad))
}
// SyObjectBase 从 box 内相对路径提取稳定文件基名并校验合法性。
// 接受形如 <rootID>.sy 的基名:扩展名必须是 .sy,且 stem 是合法节点 ID。
// 非法扩展名或非节点 ID 模式返回错误,避免把任意路径当 AAD 绑定物产生不可解密的数据。
// 由 filesys、model 历史查看/回滚、import 等所有 .sy 加解密路径共同使用,保证 AAD 一致。
func SyObjectBase(relativePath string) (string, error) {
base := relativePath
if idx := strings.LastIndexAny(relativePath, "/\\"); idx >= 0 {
base = relativePath[idx+1:]
}
if !strings.HasSuffix(base, ".sy") {
return "", fmt.Errorf("invalid .sy base name [%s]: must end with .sy", base)
}
stem := strings.TrimSuffix(base, ".sy")
if !ast.IsNodeIDPattern(stem) {
return "", fmt.Errorf("invalid .sy base name [%s]: stem is not a node ID", base)
}
return base, nil
}
// SyAAD 构造 .sy 密文的 AAD:siyuan:file:<boxID>:<稳定文件基名>。
// 父目录不进 AAD——同 box 内文件名不变的移动允许原样 Rename 密文,内容/box/类型/对象 ID 仍受认证。
func SyAAD(boxID, relativePath string) (string, error) {
base, err := SyObjectBase(relativePath)
if err != nil {
return "", err
}
return "siyuan:file:" + boxID + ":" + base, nil
}
View on GitHub (pinned to 9f775e8a12)