siyuan-note/siyuan · warning
346
346
Error message
Markdown [%s] changed after analysis: %w
What it means
Just before converting each document, the importer re-validates the source file's metadata (size/mtime via validateObsidianSourceMetadata) against what was recorded at analysis time. Any drift is wrapped as localized user error 346, 'Markdown [%s] changed after analysis', naming the file — the file's content changed after the import plan was built, so the import is aborted rather than importing a stale or mismatched document.
Solutions
- Re-run the import so the analysis captures the file's current state
- Close Obsidian and pause sync during import to prevent concurrent writes
- If only mtimes changed (touch by a tool) with identical content, re-running analysis resolves it; do not attempt to bypass the check
Defensive patterns
Strategy: retry
Validate before calling
// compare current size+mtime of each source file against the values captured at analysis time
for _, s := range analyzedSources {
if info, err := os.Stat(s.abs); err != nil || info.Size() != s.size || !info.ModTime().Equal(s.mtime) { /* changed; re-analyze */ }
} Try / catch
if code == 346 {
// the named file changed; re-run the import so the analysis reflects the current content
} Prevention
- Close Obsidian (autosave can rewrite files mid-import) before importing
- Pause sync clients so files are not updated during the import
- Avoid tools that touch mtimes (backup/indexers) on the vault during import
When it happens
Trigger: validateObsidianSourceMetadata(doc.Source) returns an error in the per-document loop — the .md file's size or modification time differs from the analysis snapshot, typically because the file was edited or re-synced after analysis.
Common situations: Obsidian open with autosave writing to the file during import; sync client downloading a newer version mid-import; build/backup tool touching mtimes without content changes.
Related errors
- 349
- 348
- block [ ] is not a sortable document
- created notebook is not mounted
- global attachment [ ] already exists
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/d056ee7eaf9489b9.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/import_obsidian.go:1867
}
if len(vault.Assets) != len(fresh.Assets) {
return newObsidianUserError(349, "", errors.New("the attachment file list changed after analysis"))
}
for key := range vault.Assets {
if fresh.Assets[key] == nil {
return newObsidianUserError(349, "", errors.New("the attachment file list changed after analysis"))
}
}
for _, doc := range vault.Docs {
if doc.Synthetic {
continue
}
if err := ctx.Err(); err != nil {
return err
}
if err := validateObsidianSourceMetadata(doc.Source); err != nil {
return newObsidianUserError(346, doc.Source.RelPath,
fmt.Errorf("Markdown [%s] changed after analysis: %w", doc.Source.RelPath, err))
}
}
for _, asset := range vault.ImportAssets {
if err := ctx.Err(); err != nil {
return err
}
if err := validateObsidianSourceMetadata(asset.Source); err != nil {
return newObsidianUserError(346, asset.Source.RelPath,
fmt.Errorf("attachment [%s] changed after analysis: %w", asset.Source.RelPath, err))
}
}
return nil
}
func validateObsidianSourceMetadata(file *obsidianSourceFile) error {
info, err := os.Stat(file.AbsPath)
if err != nil {
return errView on GitHub (pinned to 9f775e8a12)