siyuan-note/siyuan · warning
An Obsidian Vault import task is already running
Error message
An Obsidian Vault import task is already running
What it means
Returned by StartObsidianVaultAnalysis (i18n key 329) when another Obsidian import task is already active and has progressed past the pre-import states (queued/analyzing/ready). Only one import can run at a time; tasks in creating/writing/indexing/revalidating/staging states cannot be displaced. A task still in a pre-import state is cancelled and replaced silently; this error fires only for tasks that have committed to the import phase.
Source
Thrown at kernel/model/import_obsidian.go:250
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()
}
replacedTaskID = active.TaskID
finishObsidianTaskLocked(active, ObsidianTaskStateCancelled, "Import cancelled", "")
}
}
taskID := ast.NewNodeID()
ctx, cancel := context.WithCancel(context.Background())
task := &obsidianTask{TaskID: taskID, State: ObsidianTaskStateQueued, Message: "Waiting to analyze", Cancel: cancel}
obsidianTasks[taskID] = task
obsidianActive = taskID
ret := snapshotObsidianTask(task)
obsidianTasksMu.Unlock()
if replacedTaskID != "" {View on GitHub (pinned to 251596fc0d)
Solutions
- Wait for the in-progress import task to reach a terminal state (completed/failed/cancelled) before starting a new analysis.
- Call POST /api/import/cancelObsidianVaultTask with the active taskID to cancel it, then retry analysis.
- Poll GET /api/import/getObsidianVaultTask until state is terminal, then proceed.
- Ensure UI controls disable the import button while a task is active.
Example fix
// before: concurrent analysis while import is writing
// POST /api/import/startObsidianVaultAnalysis -> Language(329)
// after: cancel or wait first
task, _ := getObsidianVaultTask(activeTaskID)
if task != nil && !isTerminal(task.State) {
cancelObsidianVaultTask(activeTaskID)
}
startObsidianVaultAnalysis(newLocalPath) Defensive patterns
Strategy: validation
Validate before calling
// Check no active import is running before starting analysis
if model.IsObsidianVaultTaskActive() {
return errors.New("an Obsidian import task is already active")
} Try / catch
task, err := model.StartObsidianVaultAnalysis(localPath)
if err != nil && err.Error() == Conf.Language(329) {
// cancel the active task or wait for it, then retry
return fmt.Errorf("an import is already running (task %s); cancel it first", obsidianActive)
} Prevention
- Disable the import button in the UI while a task is active.
- Cancel or wait for the running task before initiating a new one.
- Poll IsObsidianVaultTaskActive before calling startObsidianVaultAnalysis.
When it happens
Trigger: POST /api/import/startObsidianVaultAnalysis while a prior task is in a non-terminal, non-pre-import state (isObsidianTerminalState is false and isObsidianPreImportState is false — i.e. state is revalidating, staging, creating, writing, or indexing). The second analysis call is rejected.
Common situations: User clicks 'import' again while a first import is mid-flight in the UI; a stale task ID was not cleaned up and the user retries; a scripted client fires two analysis requests concurrently.
Related errors
- The Obsidian Vault import task was not found or has expired
- The Obsidian Vault import task can no longer be cancelled
- The Obsidian Vault analysis is not ready or has expired
- Obsidian Vault is unreadable
- Obsidian Vault path is not a directory
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/ca6a7190264c15f3.
Report an issue: GitHub.