siyuan-note/siyuan · warning · ErrSYTargetNotebookRequired
target notebook required
Error message
target notebook required
What it means
ErrSYTargetNotebookRequired (import.go:148) is a sentinel returned by importSY when autoDetect is true, the archive does not look like a notebook export (no .siyuan/conf.json and no boxDocMeta), and the caller did not supply a boxID. ImportSYAuto uses it to signal the API layer that it must ask the user for a target notebook; api/import.go:142 catches it via errors.Is and stages the upload for a follow-up continueImportSY call.
Source
Thrown at kernel/model/import.go:148
if strings.HasPrefix(dest, "data:image") && strings.Contains(dest, ";base64,") {
processBase64Img(n, dest, assetDirPath, boxID)
}
}
return ast.WalkContinue
})
return
}
func ImportSY(zipPath, boxID, toPath string) (err error) {
_, err = importSY(zipPath, boxID, toPath, false, false)
return
}
func ImportSYNotebook(zipPath string) (boxID string, err error) {
return importSY(zipPath, "", "/", true, false)
}
var ErrSYTargetNotebookRequired = errors.New("target notebook required")
func ImportSYAuto(zipPath, boxID, toPath string) (createdBoxID string, notebook bool, err error) {
createdBoxID, err = importSY(zipPath, boxID, toPath, false, true)
notebook = err == nil && createdBoxID != boxID
return
}
func isSYNotebookExport(hasBoxConf, hasBoxDocMeta bool) bool {
return hasBoxConf || hasBoxDocMeta
}
func importSY(zipPath, boxID, toPath string, createNotebook, autoDetect bool) (createdBoxID string, err error) {
util.PushEndlessProgress(Conf.Language(73))
defer util.ClearPushProgress(100)
lockSync()
defer unlockSync()
View on GitHub (pinned to 251596fc0d)
Solutions
- On the client, when /api/import/importSYAuto returns a token, prompt the user to pick a notebook and call /api/import/continueImportSY with {token, notebook}.
- If the caller already knows the target, call /api/import/importSY directly with the notebook field instead of importSYAuto.
- Detect notebook-vs-document archives upstream by checking for .siyuan/conf.json before choosing the import entry point.
Example fix
// before
created, notebook, err := model.ImportSYAuto(zip, "", "/")
// after
created, notebook, err := model.ImportSYAuto(zip, "", "/")
if errors.Is(err, model.ErrSYTargetNotebookRequired) {
token := stageSYImport(zip)
// ask user for notebook, then continueImportSY(token, notebook)
} Defensive patterns
Strategy: try-catch
Validate before calling
// If you already know the target notebook, call ImportSY directly: // model.ImportSY(zipPath, boxID, toPath) // Otherwise only use ImportSYAuto and handle the sentinel.
Try / catch
created, notebook, err := model.ImportSYAuto(zipPath, boxID, toPath)
if errors.Is(err, model.ErrSYTargetNotebookRequired) {
token, _ := stageSYImport(zipPath)
// prompt user for notebook, then continueImportSY(token, chosenNotebook)
return
} Prevention
- When the target notebook is known, prefer /api/import/importSY with an explicit notebook field.
- On the client, handle the {type:"document", token} response by opening the notebook picker.
- Detect notebook-vs-document archives by checking for .siyuan/conf.json upstream.
When it happens
Trigger: POST /api/import/importSYAuto with no "notebook" field for an archive that contains only document(s) (not a notebook export). The handler responds with {type:"document", token:...} and the client must call /api/import/continueImportSY with a chosen notebook.
Common situations: User drops a .sy.zip exported from a single doc (not a notebook) into the auto-import dropzone; the archive's .siyuan/conf.json was stripped during transfer; the export predates the notebook-metadata feature.
Related errors
- 199
- rename path failed
- copy data failed
- Please unlock the encrypted notebook first
- Obsidian Vault is unreadable
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/7d870a11fe60bd04.
Report an issue: GitHub.