{"record":{"id":"aeb023503ba36494","repo":"siyuan-note/siyuan","slug":"read-form-part-s-file-s-error-s","errorCode":null,"errorMessage":"read form part [%s] file [%s] error: %s","messagePattern":"read form part \\[(.+?)\\] file \\[(.+?)\\] error: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/server.go","lineNumber":334,"sourceCode":"\t\tfor partName, fileHandlers := range multipartForm.File {\n\t\t\tfiles := make([]*RequestFile, len(fileHandlers))\n\t\t\tform.File[partName] = files\n\t\t\tfor i, handler := range fileHandlers {\n\t\t\t\tfiles[i] = &RequestFile{\n\t\t\t\t\tFilename: handler.Filename,\n\t\t\t\t\tHeaders:  handler.Header,\n\t\t\t\t\tSize:     handler.Size,\n\t\t\t\t}\n\t\t\t\tfile, openErr := handler.Open()\n\t\t\t\tif openErr != nil {\n\t\t\t\t\terr = fmt.Errorf(\"open form part [%s] file [%s] error: %s\", partName, handler.Filename, openErr.Error())\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tcontent := make([]byte, handler.Size)\n\t\t\t\tn, readErr := file.Read(content)\n\t\t\t\tfile.Close()\n\t\t\t\tif readErr != nil {\n\t\t\t\t\terr = fmt.Errorf(\"read form part [%s] file [%s] error: %s\", partName, handler.Filename, readErr.Error())\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tfileData := content[:n]\n\t\t\t\tfiles[i].Data = &fileData\n\t\t\t}\n\t\t}\n\t} else if len(c.Request.PostForm) > 0 {\n\t\t// application/x-www-form-urlencoded\n\t\tform = &RequestForm{\n\t\t\tValue: c.Request.PostForm,\n\t\t\tFile:  nil,\n\t\t}\n\t}\n\n\tif form == nil {\n\t\t// Not a form request, read raw body data\n\t\tif rawData, readErr := c.GetRawData(); readErr != nil {\n\t\t\t// request don't have body, do nothing","sourceCodeStart":316,"sourceCodeEnd":352,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/251596fc0de2f9528c00c224252fd073a99973f4/kernel/plugin/server.go#L316-L352","documentation":"Returned by the plugin server's multipart parser after handler.Open() succeeded but file.Read(content) failed while reading an uploaded file's bytes into a buffer of handler.Size. Identifies part name and filename; aborts the whole form parse.","triggerScenarios":"Reading the opened multipart file part fails — short read, stream corruption, client disconnect mid-upload, or handler.Size mismatched actual bytes. content is allocated as make([]byte, handler.Size); a read error before that many bytes triggers it.","commonSituations":"Client disconnects during upload; Content-Length lies about size; network reset; the multipart part is larger/smaller than declared and io.Reader returns an error; very large file exhausting buffers.","solutions":["Handle partial reads: use io.ReadAll or loop file.Read until EOF rather than a single Read of handler.Size.","Validate Content-Length / declared size against actual bytes before allocating.","If client disconnects are common, return a clear 4xx and let the client retry."],"exampleFix":"// before\ncontent := make([]byte, handler.Size)\nn, readErr := file.Read(content)\n// after\ncontent, readErr := io.ReadAll(io.LimitReader(file, maxUploadBytes))","handlingStrategy":"try-catch","validationCode":"// Validate declared size before allocating the read buffer.\nfunction validateUploadSize(declared: number, max: number): void {\n  if (declared <= 0) throw new Error('invalid declared size')\n  if (declared > max) throw new Error('upload exceeds max size')\n}","typeGuard":null,"tryCatchPattern":"// Robust read: loop or io.ReadAll, tolerate short reads and EOF.\nbuf := make([]byte, 0, handler.Size)\ntmp := make([]byte, 32*1024)\nfor {\n  n, err := file.Read(tmp)\n  buf = append(buf, tmp[:n]...)\n  if err == io.EOF { break }\n  if err != nil { return err }\n}","preventionTips":["Read with io.ReadAll / loop until EOF; do not rely on a single Read of declared size.","Cap upload size with io.LimitReader to bound memory.","Treat client disconnects during upload as expected, return 4xx."],"tags":["plugin","multipart","upload","io","form-parse"],"backgroundTag":null,"analyzedSha":"251596fc0de2f9528c00c224252fd073a99973f4","analyzedAt":"2026-08-12T21:18:37.123Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}