siyuan-note/siyuan · warning
Obsidian source file changed
Error message
Obsidian source file changed
What it means
A sentinel error returned when a Vault source file's size or modification time changes between the initial scan and a re-read, indicating the file was edited during analysis/import. readStableObsidianFile stats the file before and after reading; if size or mtime differ, it wraps this sentinel with 'during analysis' or 'while reading'. newObsidianReadUserError maps it to i18n key 346. This is a consistency guard: SiYuan needs the file to be stable to build accurate link/block-ID indices.
Source
Thrown at kernel/model/import_obsidian.go:235
func (err *obsidianUserError) Unwrap() error {
return err.Cause
}
func newObsidianUserError(detailLanguage int, relPath string, cause error) error {
return &obsidianUserError{DetailLanguage: detailLanguage, RelPath: relPath, Cause: cause}
}
var (
obsidianTasksMu sync.Mutex
obsidianTasks = map[string]*obsidianTask{}
obsidianActive string
errObsidianVaultUnreadable = errors.New("Obsidian Vault is unreadable")
errObsidianVaultNotDirectory = errors.New("Obsidian Vault path is not a directory")
errObsidianVaultUnsafePath = errors.New("Obsidian Vault path is unsafe")
errObsidianVaultConfigMissing = errors.New("Obsidian Vault config directory is missing")
errObsidianVaultMarkdownMissing = errors.New("Obsidian Vault has no readable Markdown")
errObsidianSourceChanged = errors.New("Obsidian source file changed")
obsidianBlockIDPattern = regexp.MustCompile(`(?m)(?:^|[ \t])\^([A-Za-z0-9-]+)[ \t]*$`)
obsidianQuotePattern = regexp.MustCompile(`^((?:[ \t]*>[ \t]?)+)(.*)$`)
obsidianListItemPattern = regexp.MustCompile(`^([ \t]*(?:[-+*]|\d+[.)])[ \t]+)(.*)$`)
obsidianFootnotePattern = regexp.MustCompile(`(?m)\[\^[^\]\r\n]+\]`)
)
func StartObsidianVaultAnalysis(localPath string) (*ObsidianVaultTask, error) {
var replacedTaskID string
obsidianTasksMu.Lock()
if obsidianActive != "" {
if active := obsidianTasks[obsidianActive]; active != nil && !isObsidianTerminalState(active.State) {
if !isObsidianPreImportState(active.State) {
obsidianTasksMu.Unlock()
return nil, errors.New(Conf.Language(329))
}
if active.Cancel != nil {
active.Cancel()View on GitHub (pinned to 251596fc0d)
Solutions
- Close Obsidian and pause any cloud-sync clients operating on the Vault before starting analysis.
- Re-run startObsidianVaultAnalysis after the Vault is quiescent — the fresh scan re-snapshots file metadata.
- Copy the Vault to a stable local directory and import the copy instead of the live Vault.
- If recurring, exclude the Vault from backup/antivirus scanning during import.
Example fix
// before: Obsidian auto-saving during import triggers mtime change // readStableObsidianFile -> errObsidianSourceChanged // after: copy vault to a quiet location first cp -r /live/Vault /tmp/VaultCopy // then POST startObsidianVaultAnalysis with localPath=/tmp/VaultCopy
Defensive patterns
Strategy: validation
Validate before calling
// Check no file changed between two stat snapshots (proxy for stability)
func vaultIsStable(vaultDir string, snapshot map[string]fs.FileInfo) (bool, error) {
for rel, old := range snapshot {
cur, err := os.Stat(filepath.Join(vaultDir, rel))
if err != nil { return false, err }
if cur.Size() != old.Size() || !cur.ModTime().Equal(old.ModTime()) {
return false, nil
}
}
return true, nil
} Try / catch
if err := analyzeVault(ctx, localPath); err != nil {
if errors.Is(err, errObsidianSourceChanged) {
// advise the user to pause sync/Obsidian and retry
return errors.New("Vault files changed during analysis; close Obsidian and sync, then retry")
}
} Prevention
- Close Obsidian and pause cloud-sync before importing.
- Copy the Vault to a quiet local directory for import.
- Avoid importing Vaults that are actively being edited.
When it happens
Trigger: During analyzeObsidianVault or importObsidianVaultTask, readStableObsidianFile (line 926) or validateObsidianSourceMetadata (line 1860) detects that a file's Size or ModTime changed between the scan snapshot and the read. Happens if Obsidian or another editor is actively saving notes into the Vault while import is running.
Common situations: Obsidian is left open and auto-saving while SiYuan imports the Vault; a cloud-sync client (Dropbox, OneDrive, iCloud) is writing files into the Vault mid-import; a user edits notes during a long analysis; antivirus or backup tools touch file metadata.
Related errors
- Obsidian Vault is unreadable
- Obsidian Vault path is not a directory
- Obsidian Vault path is unsafe
- Obsidian Vault config directory is missing
- Obsidian Vault has no readable Markdown
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/08aa1ae8416434e0.
Report an issue: GitHub.