siyuan-note/siyuan · error
encrypted asset history is missing valid notebook context
Error message
encrypted asset history is missing valid notebook context
What it means
SiYuan rolls back asset-file history by inspecting the stored history path. When the history file's content is encrypted (it starts with encryptedAssetMagic) but the path does not name a valid encrypted notebook (fewer than 3 path parts, the second part is not a notebook-ID pattern, or that notebook is not an encrypted box), the rollback is refused because there is no valid notebook context to decrypt/place the asset into.
Source
Thrown at kernel/model/history.go:562
func RollbackAssetsHistory(historyPath string) (err error) {
historyPath, err = validateHistoryPath(historyPath)
if err != nil {
return
}
from := historyPath
// 从路径提取 boxID 判断是否加密笔记本的资源
relPath := strings.TrimPrefix(filepath.ToSlash(historyPath), filepath.ToSlash(util.HistoryDir))
relPath = strings.TrimPrefix(relPath, "/")
pathParts := strings.SplitN(relPath, "/", 3)
data, readErr := filelock.ReadFile(from)
if readErr != nil {
return readErr
}
encrypted := bytes.HasPrefix(data, encryptedAssetMagic)
if encrypted && (len(pathParts) < 3 || !ast.IsNodeIDPattern(pathParts[1]) || !IsEncryptedBox(pathParts[1])) {
return errors.New("encrypted asset history is missing valid notebook context")
}
to := filepath.Join(util.DataDir, "assets", filepath.Base(historyPath))
if len(pathParts) >= 2 && IsEncryptedBox(pathParts[1]) {
if !encrypted {
return fmt.Errorf("encrypted notebook asset history is plaintext [%s]", pathParts[1])
}
// 加密笔记本的资源回滚到笔记本级 assets 目录
to = filepath.Join(util.DataDir, pathParts[1], "assets", filepath.Base(historyPath))
if err = os.MkdirAll(filepath.Dir(to), 0755); err != nil {
return
}
}
if err = filelock.CopyNewtimes(from, to); err != nil {
logging.LogErrorf("copy file [%s] to [%s] failed: %s", from, to, err)
return
}
IncSync()View on GitHub (pinned to 8641553a1f)
Solutions
- Pass the original historyPath exactly as returned by the history listing API so it retains <timestamp>-<op>/<boxID>/... structure
- Verify the notebook at pathParts[1] is actually an encrypted box (IsEncryptedBox) before rolling back encrypted assets
- Do not copy or rewrite history paths; use them verbatim from the history query results
- Regenerate the asset history entry if the source path no longer maps to a notebook
Example fix
// before: truncated path loses notebook context rollbackAssetsHistory(historyDir + "/20240101120000-update/assets/foo.enc") // after: include the notebook ID segment rollbackAssetsHistory(historyDir + "/20240101120000-update/20240101120000-xxxxxxx/assets/foo.enc")
Defensive patterns
Strategy: validation
Validate before calling
function canRollbackAssetHistory(historyPath) {
const parts = historyPath.split(/[\\/]/);
return parts.length >= 3 && /^[0-9a-f]{20}$|^[A-Za-z0-9]{20}$/.test(parts[1]);
} Type guard
null
Try / catch
try { await rollbackAssetsHistory(p); } catch (e) { if (String(e.msg).includes("missing valid notebook context")) { /* re-list history and use unmodified path */ } else { throw e; } } Prevention
- Always pass history paths verbatim from the history listing API
- Do not trim, rebase, or rebuild history path segments manually
- Confirm notebook encryption state before restoring encrypted assets
When it happens
Trigger: Calling rollbackAssetsHistory (API /api/history/rollbackAssetsHistory) with a historyPath whose file bytes are ciphertext while pathParts[1] is missing, not a 20-char node ID, or an unencrypted notebook ID.
Common situations: Hand-crafted or plugin-supplied history paths; a history file moved/copied out of its notebook history dir and passed back; testing rollback with an encrypted asset snapshot whose path lost its notebook prefix; database/index drift listing asset histories with truncated paths.
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
- encrypted notebook asset history is plaintext [%s]
- encrypted attribute view history is missing valid notebook c
- asset path must be under assets
- asset path must be a file
- source is not an encrypted asset
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/82a399270f0dd0b3.
Report an issue: GitHub.