sipeed/picoclaw · error
failed to close multipart writer: %w
Error message
failed to close multipart writer: %w
What it means
Thrown when writer.Close() fails in ElevenLabsTranscriber.Transcribe. Close writes the final multipart boundary to the bytes.Buffer; like the other WriteField failures it is only reachable through a buffer write/allocation error. If Close is skipped the Content-Type boundary would be invalid, so the code correctly aborts.
Source
Thrown at pkg/audio/asr/elevenlabs_transcriber.go:88
part, err := writer.CreateFormFile("file", filepath.Base(audioFilePath))
if err != nil {
logger.ErrorCF("voice", "Failed to create form file", map[string]any{"error": err})
return nil, fmt.Errorf("failed to create form file: %w", err)
}
if _, err = io.Copy(part, audioFile); err != nil {
logger.ErrorCF("voice", "Failed to copy file content", map[string]any{"error": err})
return nil, fmt.Errorf("failed to copy file content: %w", err)
}
if err = writer.WriteField("model_id", t.modelID); err != nil {
return nil, fmt.Errorf("failed to write model_id field: %w", err)
}
if err = writer.Close(); err != nil {
logger.ErrorCF("voice", "Failed to close multipart writer", map[string]any{"error": err})
return nil, fmt.Errorf("failed to close multipart writer: %w", err)
}
url := t.apiBase + "/v1/speech-to-text"
req, err := http.NewRequestWithContext(ctx, "POST", url, &requestBody)
if err != nil {
logger.ErrorCF("voice", "Failed to create request", map[string]any{"error": err})
return nil, fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("Xi-Api-Key", t.apiKey)
logger.DebugCF("voice", "Sending transcription request to ElevenLabs API", map[string]any{
"url": url,
"request_size_bytes": requestBody.Len(),
"file_size_bytes": fileInfo.Size(),
})
View on GitHub (pinned to 49183d7e8d)
Solutions
- Free memory headroom: cap audio duration/size at intake.
- Increase container memory limit.
- Reproduce with a stress test; if Close() fails without memory pressure, file a Go runtime issue.
Defensive patterns
Strategy: try-catch
Validate before calling
if fi, err := os.Stat(path); err == nil && fi.Size() > maxBufferedAudio {
return errors.New("audio too large; transcription would buffer it fully in RAM")
} Try / catch
if _, err := el.Transcribe(ctx, path); err != nil {
// Buffer-write failures at Close(): memory bound issue, retry with a smaller file only.
return err
} Prevention
- Bound recording size; chunk long audio into segments and transcribe per segment.
- Monitor RSS during transcription to set limits with headroom.
When it happens
Trigger: Memory allocation failure while growing the buffer for the closing boundary; effectively only under severe memory pressure after a large audio file has been buffered.
Common situations: Same as 306: cgroup memory limits vs large recordings; 32-bit builds.
Related errors
- failed to write model_id field: %w
- failed to create form file: %w
- failed to copy file content: %w
- failed to open audio file: %w
- failed to get file info: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/146bea564ab743aa.
Report an issue: GitHub.