Tencent/WeKnora · error
create form file: %w
Error message
create form file: %w
What it means
submitJob builds a multipart/form-data body and calls writer.CreateFormFile("file", filepath.Base(fileName)) to attach the uploaded document. This fails only when the multipart writer has already been closed or suffered an internal error, meaning the form body is in an invalid state. The file part could not be created, so the upload cannot proceed.
Source
Thrown at internal/infrastructure/docparser/paddleocr_vl_cloud_converter.go:131
return "", fmt.Errorf("marshal optionalPayload: %w", err)
}
fileName := req.FileName
if fileName == "" {
ext := strings.TrimPrefix(req.FileType, ".")
if ext == "" {
ext = "pdf"
}
fileName = "document." + ext
}
var body bytes.Buffer
writer := multipart.NewWriter(&body)
_ = writer.WriteField("model", c.model)
_ = writer.WriteField("optionalPayload", string(optional))
part, err := writer.CreateFormFile("file", filepath.Base(fileName))
if err != nil {
return "", fmt.Errorf("create form file: %w", err)
}
if _, err := part.Write(content); err != nil {
return "", fmt.Errorf("write file content: %w", err)
}
writer.Close()
httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, c.baseURL, &body)
if err != nil {
return "", fmt.Errorf("create request: %w", err)
}
httpReq.Header.Set("Authorization", "bearer "+c.token)
httpReq.Header.Set("Content-Type", writer.FormDataContentType())
client := utils.NewSSRFSafeHTTPClient(utils.SSRFSafeHTTPClientConfig{Timeout: 60 * time.Second, MaxRedirects: 5})
resp, err := client.Do(httpReq)
if err != nil {
return "", fmt.Errorf("HTTP request: %w", err)
}View on GitHub (pinned to 988cbb0330)
Solutions
- Verify field writes and CreateFormFile all happen before writer.Close()
- Check the wrapped error for the underlying writer state problem
- Ensure CreateFormFile is called exactly once per upload with a valid, non-empty filename from filepath.Base
- If triggered by OOM pressure on the buffer, stream to a temp file instead of an in-memory bytes.Buffer for very large documents
Example fix
// before
writer.Close()
part, err := writer.CreateFormFile("file", name) // fails: writer closed
// after
part, err := writer.CreateFormFile("file", name)
if _, err := part.Write(content); err != nil { ... }
writer.Close() Defensive patterns
Strategy: try-catch
Validate before calling
if fileName == "" { return errors.New("file name required for multipart upload") }
if err == nil && writerClosed { return errors.New("multipart writer closed before file part created") } Type guard
func isFormFileError(err error) bool {
return err != nil && strings.Contains(err.Error(), "create form file")
} Try / catch
out, err := reader.Read(ctx, req)
if isFormFileError(err) {
return fmt.Errorf("multipart assembly bug (check write/close ordering): %w", err)
} Prevention
- Always create all parts before calling writer.Close()
- Call CreateFormFile exactly once per upload
- Use filepath.Base to sanitize user-supplied file names
- Add a regression test covering the full multipart build for each Read path
When it happens
Trigger: Read -> submitJob -> CreateFormFile returns an error — occurs when writer.Close() was called before CreateFormFile, or the multipart writer is otherwise in an error state (e.g. a prior WriteField write already poisoned it after an underlying io error on the buffer).
Common situations: Code refactors that reordered Close() before CreateFormFile; a bytes.Buffer write failure (virtually only under memory exhaustion); duplicating a part with the same field name after Close.
Related errors
- write file content: %w
- failed to upload file to OSS (multipart): %w
- PaddleOCR-VL Cloud submit: %w
- PaddleOCR-VL Cloud fetch results: %w
- marshal optionalPayload: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/437e25a7eb144770.
Report an issue: GitHub.