{"record":{"id":"c7564e1d403c77cb","repo":"Tencent/WeKnora","slug":"write-file-content-w-c7564e","errorCode":null,"errorMessage":"write file content: %w","messagePattern":"write file content: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/infrastructure/docparser/paddleocr_vl_cloud_converter.go","lineNumber":134,"sourceCode":"\tfileName := req.FileName\n\tif fileName == \"\" {\n\t\text := strings.TrimPrefix(req.FileType, \".\")\n\t\tif ext == \"\" {\n\t\t\text = \"pdf\"\n\t\t}\n\t\tfileName = \"document.\" + ext\n\t}\n\n\tvar body bytes.Buffer\n\twriter := multipart.NewWriter(&body)\n\t_ = writer.WriteField(\"model\", c.model)\n\t_ = writer.WriteField(\"optionalPayload\", string(optional))\n\tpart, err := writer.CreateFormFile(\"file\", filepath.Base(fileName))\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"create form file: %w\", err)\n\t}\n\tif _, err := part.Write(content); err != nil {\n\t\treturn \"\", fmt.Errorf(\"write file content: %w\", err)\n\t}\n\twriter.Close()\n\n\thttpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, c.baseURL, &body)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"create request: %w\", err)\n\t}\n\thttpReq.Header.Set(\"Authorization\", \"bearer \"+c.token)\n\thttpReq.Header.Set(\"Content-Type\", writer.FormDataContentType())\n\n\tclient := utils.NewSSRFSafeHTTPClient(utils.SSRFSafeHTTPClientConfig{Timeout: 60 * time.Second, MaxRedirects: 5})\n\tresp, err := client.Do(httpReq)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"HTTP request: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\trespBody, _ := io.ReadAll(resp.Body)","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/docparser/paddleocr_vl_cloud_converter.go#L116-L152","documentation":"Immediately after creating the 'file' part, submitJob writes the whole document bytes into it via part.Write(content). If that write fails — practically only when the underlying buffer/connection errors or memory is exhausted — the error is wrapped as 'write file content'. The multipart request could not be assembled with the document payload.","triggerScenarios":"Read -> submitJob -> part.Write(content) returns an error on a large content payload; effectively indicates an io.Writer failure on the multipart part's underlying writer (bytes.Buffer allocation failure) or an already-closed/errored writer.","commonSituations":"Uploading very large documents causing the in-memory bytes.Buffer to exhaust memory; writer closed prematurely after a refactor; content slice referencing unavailable data (rare).","solutions":["Check the wrapped cause for the underlying io error","For large files, stream content to a temp file and use os.Open as the request body instead of buffering fully in memory","Ensure part.Write occurs before writer.Close()","Retest with a smaller document to isolate size-related memory pressure"],"exampleFix":"// before\nvar body bytes.Buffer\nwriter := multipart.NewWriter(&body) // large file -> memory pressure\n// after\nf, _ := os.CreateTemp(\"\", \"paddleocr-*\")\nwriter := multipart.NewWriter(f) // stream to disk-backed buffer","handlingStrategy":"validation","validationCode":"if len(content) > 100<<20 { // 100 MB\n    return fmt.Errorf(\"document too large for in-memory upload: %d bytes\", len(content))\n}","typeGuard":"func isPartWriteError(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"write file content\")\n}","tryCatchPattern":"out, err := reader.Read(ctx, req)\nif isPartWriteError(err) {\n    if errors.Is(err, ErrWriterClosed) { return fmt.Errorf(\"ordering bug: write after close\") }\n    return fmt.Errorf(\"upload payload write failed (consider streaming): %w\", err)\n}","preventionTips":["Prefer disk-backed streaming for documents beyond tens of MB","Write file parts strictly before writer.Close()","Monitor memory headroom on hosts parsing large documents","Cap upload size at the cloud API's documented limit before submitting"],"tags":["io","multipart","upload","paddleocr","memory"],"backgroundTag":"multipart-write-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}