siyuan-note/siyuan · error

panic during siyuan.storage.put

Error message

panic during siyuan.storage.put: %v

What it means

The goroutine performing the mkdir/write for siyuan.storage.put(path, content) recovered from a Go panic; the panic value is embedded and the Promise rejected. Normal I/O failures are reported with their own messages; this wrapper indicates an unexpected internal defect during the put pipeline.

Solutions

  1. Inspect the embedded panic value in the rejection for the concrete cause
  2. Serialize your plugin's storage.put calls (await each before the next) to rule out races
  3. Retry the put once — transient races often succeed on the second attempt
  4. Report reproducible panics with the message text to the SiYuan kernel maintainers

Example fix

// before
await Promise.all(paths.map(p => siyuan.storage.put(p, data)));
// after
for (const p of paths) {
  try { await siyuan.storage.put(p, data); }
  catch (e) { console.error("put failed:", e.message); }
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (typeof path !== "string" || typeof content !== "string") throw new TypeError("put requires string path and content");

Type guard

null

Try / catch

try { await siyuan.storage.put(path, content); } catch (e) { console.error("storage.put panic:", e.message); await retryOnce(() => siyuan.storage.put(path, content)); }

Prevention

When it happens

Trigger: A panic in os.MkdirAll, filelock.WriteFile, or the result/resolution code path inside the put goroutine; nil dereferences or slice bugs in the storage layer under concurrency or unusual filesystem states.

Common situations: Race conditions between concurrent puts from the same plugin; kernel-internal bugs; exotic filesystem states (e.g. path component becoming a file mid-write) that trip an unchecked assumption.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/a5fddff4d7f93b0f. Report an issue: GitHub.

Appendix: source

Thrown at kernel/plugin/api_storage.go:260

			if argErr != nil {
				err = argErr
				return
			}
			if util.ReadOnly {
				err = fmt.Errorf("The current kernel is in read-only mode, storage.put is not allowed")
				return
			}

			abs, resolveErr := resolvePath(path)
			if resolveErr != nil {
				err = resolveErr
				return
			}

			go func() (result any, err error) {
				defer func() {
					if r := recover(); r != nil {
						err = fmt.Errorf("panic during siyuan.storage.put: %v", r)
					}

					p.worker.Run(func(rt *goja.Runtime) (_ any, _ error) {
						if lo.IsNil(err) {
							if resolveErr := resolve(result); resolveErr != nil {
								logging.LogErrorf("[plugin:%s] siyuan.storage.put resolve: %v", p.Name, resolveErr)
							}
						} else {
							if rejectErr := reject(rt.NewGoError(err)); rejectErr != nil {
								logging.LogErrorf("[plugin:%s] siyuan.storage.put reject: %v", p.Name, rejectErr)
							}
						}
						return
					}, nil)
				}()

				if mkdirErr := os.MkdirAll(filepath.Dir(abs), 0755); mkdirErr != nil {
					err = fmt.Errorf("failed to make directory: %w", mkdirErr)

View on GitHub (pinned to 9f775e8a12)