siyuan-note/siyuan · error
target document not found in notebook
Error message
target document not found in notebook %s: %s
What it means
resolveMarkdownImportTarget maps the user-supplied target path (toPath) for a Markdown import to an existing document in the target notebook via the block tree. If no document root matches the normalized path, the import cannot determine the parent document and returns this error. Empty toPath ('/') is allowed (import to notebook root); anything else must point at an existing .sy document.
Solutions
- Verify the target document exists in the notebook and pass its current path (from the doc tree) as toPath
- Pass "/" as toPath to import to the notebook root instead of under a specific document
- Refresh/reindex the notebook if the block tree is stale (rebuild index), then retry
- If calling the API, obtain toPath from a document lookup (e.g. filetree/doc listing) rather than hardcoding it
Example fix
// before: stale/foreign path
curl -d '{"notebook":"20240102150405-abc","localPath":"/tmp/notes","toPath":"/20240102150405-deleted-doc.sy"}' /api/import/importFromPath
// after: import to notebook root, or a verified existing doc path
curl -d '{"notebook":"20240102150405-abc","localPath":"/tmp/notes","toPath":"/"}' /api/import/importFromPath Defensive patterns
Strategy: validation
Validate before calling
// Caller-side (before /api/import/importFromPath): confirm the target doc exists
// via the block-tree/filetree API; pass "/" to import at notebook root
const target = "/20240102150405-existing-doc.sy"
const ok = (await fetchPost("/api/filetree/getDoc", {id: docID})).code === 0
// or simply use toPath: "/" when unsure Try / catch
try {
await fetchPost("/api/import/importFromPath", {notebook, localPath, toPath});
} catch (e) {
if (String(e.msg).startsWith("target document not found")) {
// fall back to notebook root or re-resolve toPath from the doc tree
toPath = "/";
}
} Prevention
- Resolve toPath from the live document tree at call time, never cache it across renames/deletes
- Use "/" when importing to the notebook root is acceptable
- Never build toPath by hand for a different notebook than boxID
- After bulk deletes or reindex, re-fetch target paths before importing
When it happens
Trigger: Calling ImportFromLocalPath / ImportFromLocalPathSkipRoot / ValidateImportFromLocalPath with a toPath that names a document that does not exist in boxID — typically a stale or typoed hpath-derived path, or a path belonging to another notebook.
Common situations: Frontend passing a toPath captured before the target document was deleted or renamed; cross-notebook drag-drop with a path from the wrong notebook; API callers constructing toPath by hand without .sy normalization; stale block-tree index after reindexing.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Conf.Language(79)
- import from local path failed, please check kernel log for…
- parse tree [ ] failed
- 0
- 199
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/c4870f6d74de547f.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/model/import.go:1500
if _, err := os.Stat(localPath); err != nil {
return err
}
_, _, err := resolveMarkdownImportTarget(boxID, toPath)
return err
}
func resolveMarkdownImportTarget(boxID, toPath string) (baseHPath, baseTargetPath string, err error) {
toPath = path.Clean("/" + strings.TrimPrefix(toPath, "/"))
if toPath != "/" && !strings.HasSuffix(toPath, ".sy") {
toPath += ".sy"
}
toPath = normalizeBoxDocTarget(boxID, toPath)
if toPath == "/" {
return "/", "/", nil
}
block := treenode.GetBlockTreeRootByPath(boxID, toPath)
if block == nil || block.ID == "" {
return "", "", fmt.Errorf("target document not found in notebook %s: %s", boxID, toPath)
}
return block.HPath, strings.TrimSuffix(block.Path, ".sy"), nil
}
func importFromLocalPath(boxID, localPath string, toPath string, skipRoot bool) (err error) {
box, err := getOpenedBox(boxID)
if nil != err {
return err
}
util.PushEndlessProgress(Conf.Language(73))
defer func() {
util.PushClearProgress()
if e := recover(); nil != e {
stack := debug.Stack()
msg := fmt.Sprintf("PANIC RECOVERED: %v\n\t%s\n", e, stack)
logging.LogErrorf("import from local path failed: %s", msg)
err = errors.New("import from local path failed, please check kernel log for details")View on GitHub (pinned to 9f775e8a12)