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

  1. 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}.
  2. If the caller already knows the target, call /api/import/importSY directly with the notebook field instead of importSYAuto.
  3. 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 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


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