siyuan-note/siyuan · error · obsidianUserError

346

346

Error message

Markdown [%s] changed after analysis: %w

What it means

Per-file markdown drift in revalidateObsidianVault: validateObsidianSourceMetadata(doc.Source) failed because os.Stat now reports a Size or ModTime different from the snapshot taken at scan time. Reported with code 346 ('File [%s] changed after analysis; analyze the Vault again'). This is a finer-grained version of 788/789: even if the file set is stable, content edits are caught by size/mtime.

Source

Thrown at kernel/model/import_obsidian.go:1845

	}
	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 err

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Stop editing the vault, re-run StartObsidianVaultAnalysis, then immediately import.
  2. Pause sync/Git for the vault during the analyse→import window.
  3. If mtime drift is spurious (network FS), copy the vault to a local FS and import from there.
  4. Disable auto-save or touch-on-open editors for the vault until import completes.

Example fix

// before: edit a note after analysis -> size/mtime differ -> 346
//   echo 'new line' >> notes/daily.md  (after analysis)

// after: finish edits, re-analyse, then import without further edits
StartObsidianVaultAnalysis(vault)
StartObsidianVaultImport(taskID, nb)
Defensive patterns

Strategy: validation

Validate before calling

// Verify no markdown size/mtime drift since analysis.
func markdownUnchanged(vault string, snap map[string]fileMeta) error { /* compare os.Stat vs snap */ }

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: A markdown file that existed at both times was edited in place: its size and/or mtime changed. Common when the user keeps taking notes in Obsidian after analysis, or a sync client rewrote the file body without adding/removing it.

Common situations: Active note-taking during import; cloud sync pushing content updates; Git pull updating file bodies; an editor's auto-save touching mtime without a real edit; filesystem mtime resolution causing spurious differences on some network FS.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/d056ee7eaf9489b9. Report an issue: GitHub.