siyuan-note/siyuan · error
199
199
Error message
This is not a valid .sy.zip archive. If the archive was exported from [Settings], please import it from [Settings]
What it means
Returned by importSY (import.go:198) as Conf.Language(199) = "This is not a valid .sy.zip archive. If the archive was exported from [Settings], please import it from [Settings]". Fires when the unzipped directory does not contain exactly one top-level directory entry or contains zero .sy files. The kernel expects a single root folder holding the .sy tree; anything else (flat zip, multi-root, empty zip) is rejected as malformed.
Source
Thrown at kernel/model/import.go:198
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() || len(syPaths) < 1 {
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 251596fc0d)
Solutions
- Re-export the notebook/document from SiYuan and import the untouched .sy.zip.
- If the user exported full data from Settings, import it from Settings - Export - Import Data, not the notebook import dialog.
- Inspect the zip's top-level layout: it must be exactly one directory containing .sy files.
Defensive patterns
Strategy: validation
Validate before calling
// Inspect the zip before importing: it must contain exactly one top-level dir holding .sy files.
entries, _ := zip.OpenReader(zipPath)
defer entries.Close()
topDirs := 0; hasSy := false
for _, f := range entries.File {
seg := strings.Split(strings.TrimPrefix(f.Name, "/"), "/")[0]
if seg != "" { topDirs = 1 }
if strings.HasSuffix(f.Name, ".sy") { hasSy = true }
}
if topDirs != 1 || !hasSy { return errors.New(Conf.Language(199)) } Try / catch
err := model.ImportSY(zipPath, boxID, toPath)
if err != nil && err.Error() == Conf.Language(199) {
// tell user the archive is not a valid .sy.zip; re-export or use Settings import
} Prevention
- Do not re-compress .sy.zip exports with third-party tools that change layout.
- Use the matching import entry point: notebook/doc import vs Settings - Data import.
- Verify the zip has one top-level directory containing .sy files before upload.
When it happens
Trigger: POST /api/import/importSY, importSYNotebook, or importSYAuto with a zip that is not a SiYuan .sy.zip export: a generic zip, a re-zipped folder whose structure was flattened, an empty archive, or a Data export mistaken for a notebook/doc export.
Common situations: User re-compressed the export with a different tool that changed the layout; user exported from Settings - Export - Data and tries to import via the notebook import dialog (wrong direction); corrupted download.
Related errors
- invalid import token
- no file found
- import path is not sub path of import dir
- --file is required
- --notebook is required
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/6b33c253b6d98879.
Report an issue: GitHub.