siyuan-note/siyuan · error

workspace changed during asset scan; retry the request

Error message

workspace changed during asset scan; retry the request: %s

What it means

During scanning, the plan snapshots stat stamps (existence, size, mtime, mode) of the files it will rewrite. validateSnapshot re-checks them before apply; if any file changed between scan and apply, or appeared/disappeared unexpectedly, the plan aborts with this error to avoid rewriting stale in-memory content over newer data.

Solutions

  1. Re-run the whole relink request so the scan and apply happen back-to-back on unchanged data
  2. Pause sync and close other clients editing the workspace during the batch operation
  3. Retry with exponential backoff in automation, and reduce batch size to shorten the scan window
  4. Exclude the workspace from backup/AV tools that rewrite mtimes during the operation

Example fix

// before
_, err := model.RelinkAssets(ctx, bigBatch, false) // long scan, files change mid-way
// after
chunks := chunk(mappings, 20) // smaller windows
for _, c := range chunks {
	if _, err := model.RelinkAssets(ctx, c, false); err != nil {
		return retryWithBackoff(c) // rescan on 'workspace changed'
	}
}
Defensive patterns

Strategy: retry

Try / catch

result, err := model.RelinkAssets(ctx, mappings, dryRun)
if err != nil && strings.Contains(fmt.Sprint(err), "workspace changed") {
	time.Sleep(time.Second)
	result, err = model.RelinkAssets(ctx, mappings, dryRun) // fresh scan+apply
}

Prevention

When it happens

Trigger: Any file targeted by the scan is modified, moved, replaced, or deleted between the scan phase and apply(); another client or sync process edits documents or assets during a long-running batch scan.

Common situations: Sync engine downloading changes mid-scan; a second SiYuan client editing the same workspace; user edits documents while a large batch scan is running; system clock or filesystem touching mtimes (e.g. backup tools).

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/96cce1276108cf82. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/asset_relink_batch.go:242

	}
	if err != nil {
		return err
	}
	p.inventory[path] = assetRelinkStamp{true, info.Size(), info.ModTime(), info.Mode()}
	return nil
}

func (p *assetRelinkPlan) validateSnapshot() error {
	for path, stamp := range p.inventory {
		if err := p.checkContext(); err != nil {
			return err
		}
		info, err := os.Stat(path)
		if !stamp.exists && os.IsNotExist(err) {
			continue
		}
		if err != nil || !stamp.exists || stamp.size != info.Size() || !stamp.modified.Equal(info.ModTime()) || stamp.mode != info.Mode() {
			return fmt.Errorf("workspace changed during asset scan; retry the request: %s", path)
		}
	}
	return nil
}

// mayContainReferences 仅排除没有目标文件名且没有任何转义的源;转义一律进入语义解析以防漏筛。
func (p *assetRelinkPlan) mayContainReferences(data []byte) bool {
	if bytes.ContainsAny(data, "\\%&") {
		return true
	}
	return len(p.matcher.SearchIndexed(string(data))) > 0
}

func (p *assetRelinkPlan) itemsForPath(path string) map[*assetRelinkItem]bool {
	ret := map[*assetRelinkItem]bool{}
	if item := p.itemByPath[path]; item != nil {
		ret[item] = true
	}

View on GitHub (pinned to 9f775e8a12)