siyuan-note/siyuan · error · errObsidianSourceChanged
during analysis
Error message
%w during analysis
What it means
A Vault file changed between the initial scan and the moment it was read for analysis. readStableObsidianFile stats the file before reading and compares size and modification time against the values captured during the scan; a mismatch is wrapped in errObsidianSourceChanged with the context 'during analysis', so callers can detect it with errors.Is. This guarantees the import operates on a stable snapshot.
Solutions
- Close Obsidian and any other editors, then re-run the import
- Pause cloud-sync/backup tools that touch the vault during import
- Make a static copy of the vault and import the copy
- Re-run the import — a stable vault will pass the before-stat check
Example fix
// before: importing a live vault
importFrom(vaultDir)
// after: import a quiescent snapshot
cp -r vaultDir /tmp/vault-snapshot
importFrom("/tmp/vault-snapshot") Defensive patterns
Strategy: retry
Try / catch
try {
await importObsidianVault(vaultPath);
} catch (e) {
if (errors.Is(e, errObsidianSourceChanged)) {
await retryImport(vaultPath); // after quiescing editors/sync
}
} Prevention
- Close Obsidian and pause sync/backup tools during import
- Import from a frozen snapshot copy of the vault
- Disable autosave temporarily if the vault is actively edited
When it happens
Trigger: os.Stat(file.AbsPath) succeeds but before.Size() != file.Size or !before.ModTime().Equal(file.ModTime) — the file was modified (or replaced) after scanObsidianVaultFiles recorded its metadata.
Common situations: Obsidian (or another editor) is open and autosaves during the import; a sync client (iCloud/Dropbox/Syncthing) updates files concurrently; backup tools touch mtimes.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/013215a305918af8.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/import_obsidian.go:932
}
}
tree, _, _, _ := parseStdMd(data)
if tree == nil {
return newObsidianUserError(347, doc.Source.RelPath,
fmt.Errorf("parse Markdown [%s] failed", doc.Source.RelPath))
}
analyzeObsidianMarkdownLinks(vault, doc, tree)
}
return nil
}
func readStableObsidianFile(file *obsidianSourceFile) ([]byte, error) {
before, err := os.Stat(file.AbsPath)
if err != nil {
return nil, err
}
if before.Size() != file.Size || !before.ModTime().Equal(file.ModTime) {
return nil, fmt.Errorf("%w during analysis", errObsidianSourceChanged)
}
data, err := os.ReadFile(file.AbsPath)
if err != nil {
return nil, err
}
after, err := os.Stat(file.AbsPath)
if err != nil {
return nil, err
}
if before.Size() != after.Size() || !before.ModTime().Equal(after.ModTime()) {
return nil, fmt.Errorf("%w while reading", errObsidianSourceChanged)
}
return data, nil
}
func newObsidianReadUserError(file *obsidianSourceFile, err error) error {
language := 345
if errors.Is(err, errObsidianSourceChanged) {View on GitHub (pinned to 9f775e8a12)