siyuan-note/siyuan · error

open form part [ ] file [ ] error

Error message

open form part [%s] file [%s] error: %s

What it means

When parsing a multipart form upload, the plugin server opens each file part via handler.Open(); if opening the uploaded file fails (disk/temp-file error), the error is wrapped with the part name and client-provided filename and returned to the caller.

Solutions

  1. Check the error suffix (%s) for the underlying cause and fix it (free disk space, raise ulimit -n)
  2. Retry the upload; transient EMFILE usually resolves after load drops
  3. Ensure the client sends well-formed multipart/form-data with valid file parts
Defensive patterns

Strategy: retry

Validate before calling

null

Type guard

null

Try / catch

try { await uploadFile(form); } catch (e) { if (String(e).includes('open form part')) { await sleep(1000); await uploadFile(form); } else { throw e; } }

Prevention

When it happens

Trigger: Uploading a file through the plugin server's multipart endpoint when the server cannot open the multipart part's underlying temp file - e.g. OS temp directory issues, too many open files, or corrupted multipart encoding.

Common situations: Server host with a full or unwritable temp directory, EMFILE (too many open files) under heavy concurrent uploads, or a client sending malformed multipart bodies.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at kernel/plugin/server.go:327

	} else if multipartForm != nil {
		// multipart/form-data
		form = &RequestForm{
			Value: multipartForm.Value,
			File:  make(map[string][]*RequestFile),
		}

		for partName, fileHandlers := range multipartForm.File {
			files := make([]*RequestFile, len(fileHandlers))
			form.File[partName] = files
			for i, handler := range fileHandlers {
				files[i] = &RequestFile{
					Filename: handler.Filename,
					Headers:  handler.Header,
					Size:     handler.Size,
				}
				file, openErr := handler.Open()
				if openErr != nil {
					err = fmt.Errorf("open form part [%s] file [%s] error: %s", partName, handler.Filename, openErr.Error())
					return
				}
				content := make([]byte, handler.Size)
				n, readErr := file.Read(content)
				file.Close()
				if readErr != nil {
					err = fmt.Errorf("read form part [%s] file [%s] error: %s", partName, handler.Filename, readErr.Error())
					return
				}
				fileData := content[:n]
				files[i].Data = &fileData
			}
		}
	} else if len(c.Request.PostForm) > 0 {
		// application/x-www-form-urlencoded
		form = &RequestForm{
			Value: c.Request.PostForm,
			File:  nil,

View on GitHub (pinned to 9f775e8a12)