{"record":{"id":"7a30d1038362de89","repo":"siyuan-note/siyuan","slug":"export-failed-empty-artifact-path","errorCode":null,"errorMessage":"export failed: empty artifact path","messagePattern":"export failed: empty artifact path","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/cli/cmd/export.go","lineNumber":226,"sourceCode":"\n\t\tzipPath, err := model.ExportData()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tresultPath, err := materializeExportArtifact(zipPath, output)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif output == \"\" {\n\t\t\tfmt.Println(resultPath)\n\t\t}\n\t\treturn nil\n\t},\n}\n\nfunc materializeExportArtifact(exportPath, output string) (resultPath string, err error) {\n\tif exportPath == \"\" {\n\t\treturn \"\", fmt.Errorf(\"export failed: empty artifact path\")\n\t}\n\tlease, err := model.AcquireExportArtifactLease(exportPath)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer model.ReleaseExportArtifactLease(lease.ID)\n\n\tif output == \"\" {\n\t\treturn lease.Path, nil\n\t}\n\tif err = filelock.Copy(lease.Path, output); err != nil {\n\t\treturn \"\", err\n\t}\n\treturn output, nil\n}\n\nfunc init() {\n\texportMdCmd.Flags().String(\"id\", \"\", \"block ID\")","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/afa823b6b4e4f183511e0bc0a3be93caa94c7c97/kernel/cli/cmd/export.go#L208-L244","documentation":"materializeExportArtifact is the shared helper behind `export sy`, `export md-zip`, and `export data`: it takes the zip path returned by the model export routine, acquires an artifact lease on it, and either copies it to `--output` or returns the leased path. Its first statement asserts the path is non-empty. Crucially, the callers discard the error return of model.ExportPandocConvertZip with `_`, so when the underlying export fails (e.g. pandoc unavailable, invalid document) and yields an empty path, this guard is what surfaces the problem. It therefore indicates a failed or silently-short-circuited export, not a flag mistake.","triggerScenarios":"Running `siyuan export sy --id <id>` or `siyuan export md-zip --id <id>` (with or without `--output`) when model.ExportPandocConvertZip returns an empty zip path; likewise `siyuan export data` when model.ExportData returns an empty path. Typical root causes: nonexistent/deleted document ID, pandoc not installed or failing during conversion, or an export routine that aborted without propagating its error.","commonSituations":"Exporting an ID captured before the document was deleted or renamed; environments where the pandoc binary is missing from PATH (md-zip and sy conversion depend on it); kernel versions where the export routine swallows errors; full or read-only temp/export directories.","solutions":["Confirm the document ID is valid: open it in the UI or find it with `siyuan document search`, then retry","Check the kernel log for the real underlying failure — the returned error was discarded before this guard fired","For md-zip/sy exports, verify pandoc is installed and on PATH (`pandoc --version`) since the conversion zip goes through it","Check the workspace temp/export directories are writable and not full","If it reproduces on a valid ID with a healthy environment, report it as a bug: an export returning an empty path without an error is a kernel defect (the CLI should propagate model.ExportPandocConvertZip's error instead of discarding it)"],"exampleFix":"// before (kernel/cli/cmd/export.go)\n_, zipPath := model.ExportPandocConvertZip([]string{id}, \"\", \".sy\")\nresultPath, err := materializeExportArtifact(zipPath, output)\n// after\nif _, zipPath := model.ExportPandocConvertZip([]string{id}, \"\", \".sy\"); zipPath == \"\" {\n    return fmt.Errorf(\"sy export produced no artifact for document %s\", id)\n}\n// or capture and check the discarded error return","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"run_export() {\n  siyuan export sy --id \"$1\" --output \"$2\" 2>err.txt\n}\nif ! run_export \"$ID\" out.zip; then\n  sleep 2\n  if ! run_export \"$ID\" out.zip; then\n    echo \"export produced no artifact; check kernel log and pandoc\" >&2; exit 1\n  fi\nfi","preventionTips":["Verify pandoc is installed and on PATH before md-zip/sy exports","Confirm the document ID exists and opens before exporting","Watch kernel logs during automated exports; this error means a real failure was swallowed","For programmatic use, check the returned artifact path for emptiness before downstream steps"],"tags":["cli","export","artifact","internal-error","invariant","pandoc","sy-zip"],"backgroundTag":"export-empty-artifact","analyzedSha":"afa823b6b4e4f183511e0bc0a3be93caa94c7c97","analyzedAt":"2026-08-18T17:04:10.865Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}