siyuan-note/siyuan · error
Conf.Language(199)
Error message
Conf.Language(199)
What it means
importSY0 validates the shape of an unpacked .sy.zip: the unzip directory must contain exactly one entry and it must be a directory. Anything else is rejected with i18n key 199 ('This is not a valid .sy.zip archive...'). This guards against arbitrary zips or archives with files at the root.
Source
Thrown at kernel/model/import.go:353
return err
}
if d == nil {
return nil
}
if !d.IsDir() && strings.HasSuffix(d.Name(), ".sy") {
syPaths = append(syPaths, path)
}
return nil
})
entries, err := os.ReadDir(unzipPath)
if err != nil {
logging.LogErrorf("read unzip dir [%s] failed: %s", unzipPath, err)
return
}
if 1 != len(entries) || !entries[0].IsDir() {
logging.LogErrorf("invalid .sy.zip [%v]", entries)
err = errors.New(Conf.Language(199))
return
}
unzipRootPath := filepath.Join(unzipPath, entries[0].Name())
name := filepath.Base(unzipRootPath)
if strings.HasPrefix(name, "data-20") && len("data-20230321175442") == len(name) {
logging.LogErrorf("invalid .sy.zip [unzipRootPath=%s, baseName=%s]", unzipRootPath, name)
err = errors.New(Conf.Language(199))
return
}
var importedBoxConf *conf.BoxConf
importedConfPath := filepath.Join(unzipRootPath, ".siyuan", "conf.json")
hasImportedBoxConf := filelock.IsExist(importedConfPath)
var importedMetadataErr error
if hasImportedBoxConf {
confData, readErr := filelock.ReadFile(importedConfPath)
if readErr == nil {
importedBoxConf = conf.NewBoxConf()
if unmarshalErr := gulu.JSON.UnmarshalJSON(confData, importedBoxConf); unmarshalErr != nil {View on GitHub (pinned to 8641553a1f)
Solutions
- Re-export the .sy.zip from SiYuan (doc tree or Settings) without modifying the archive structure
- Ensure the zip contains exactly one root directory (e.g. the notebook export folder)
- If re-packaging manually, wrap all contents in a single top-level directory before zipping
- Verify the archive is not corrupted (test extraction) before importing
Defensive patterns
Strategy: validation
Validate before calling
// validate zip layout before import: exactly one top-level directory
f, _ := zip.OpenReader(zipPath)
defer f.Close()
tops := map[string]bool{}
for _, zf := range f.File {
parts := strings.SplitN(zf.Name, "/", 2)
tops[parts[0]] = true
}
if len(tops) != 1 {
return errors.New("zip must contain a single root directory")
} Try / catch
// Go caller
if err := model.ImportSY(zipPath, boxID, toPath); err != nil {
logging.LogErrorf("invalid .sy.zip layout: %s", err)
return fmt.Errorf("please re-export the archive from SiYuan")
} Prevention
- Never re-zip exported archives without their single root folder
- Import only archives produced by SiYuan's export feature
- Test-extract the zip before importing
When it happens
Trigger: Calling ImportSY / ImportSYAuto / ImportSYNotebookBundle with a zip that, after unzip, yields multiple entries at the top level or a top-level file instead of a single directory (e.g. a .sy.zip without its enclosing folder, a renamed random .zip, or a corrupted archive).
Common situations: Manually re-zipping documents without the single root folder; downloading a partial archive; passing a plain zip of .sy files instead of the exported .sy.zip; macOS archive tools that strip the wrapper folder.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- 199
- unzip failed:
- This archive contains notebook data. Please import it from [
- This is not a valid .sy.zip archive. If the archive was expo
- Query notebook failed
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/612945c186c7f1b9.
Report an issue: GitHub.