{"record":{"id":"146bea564ab743aa","repo":"sipeed/picoclaw","slug":"failed-to-close-multipart-writer-w","errorCode":null,"errorMessage":"failed to close multipart writer: %w","messagePattern":"failed to close multipart writer: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/audio/asr/elevenlabs_transcriber.go","lineNumber":88,"sourceCode":"\n\tpart, err := writer.CreateFormFile(\"file\", filepath.Base(audioFilePath))\n\tif err != nil {\n\t\tlogger.ErrorCF(\"voice\", \"Failed to create form file\", map[string]any{\"error\": err})\n\t\treturn nil, fmt.Errorf(\"failed to create form file: %w\", err)\n\t}\n\n\tif _, err = io.Copy(part, audioFile); err != nil {\n\t\tlogger.ErrorCF(\"voice\", \"Failed to copy file content\", map[string]any{\"error\": err})\n\t\treturn nil, fmt.Errorf(\"failed to copy file content: %w\", err)\n\t}\n\n\tif err = writer.WriteField(\"model_id\", t.modelID); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to write model_id field: %w\", err)\n\t}\n\n\tif err = writer.Close(); err != nil {\n\t\tlogger.ErrorCF(\"voice\", \"Failed to close multipart writer\", map[string]any{\"error\": err})\n\t\treturn nil, fmt.Errorf(\"failed to close multipart writer: %w\", err)\n\t}\n\n\turl := t.apiBase + \"/v1/speech-to-text\"\n\treq, err := http.NewRequestWithContext(ctx, \"POST\", url, &requestBody)\n\tif err != nil {\n\t\tlogger.ErrorCF(\"voice\", \"Failed to create request\", map[string]any{\"error\": err})\n\t\treturn nil, fmt.Errorf(\"failed to create request: %w\", err)\n\t}\n\n\treq.Header.Set(\"Content-Type\", writer.FormDataContentType())\n\treq.Header.Set(\"Xi-Api-Key\", t.apiKey)\n\n\tlogger.DebugCF(\"voice\", \"Sending transcription request to ElevenLabs API\", map[string]any{\n\t\t\"url\":                url,\n\t\t\"request_size_bytes\": requestBody.Len(),\n\t\t\"file_size_bytes\":    fileInfo.Size(),\n\t})\n","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/audio/asr/elevenlabs_transcriber.go#L70-L106","documentation":"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.","triggerScenarios":"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.","commonSituations":"Same as 306: cgroup memory limits vs large recordings; 32-bit builds.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if fi, err := os.Stat(path); err == nil && fi.Size() > maxBufferedAudio {\n    return errors.New(\"audio too large; transcription would buffer it fully in RAM\")\n}","typeGuard":null,"tryCatchPattern":"if _, err := el.Transcribe(ctx, path); err != nil {\n    // Buffer-write failures at Close(): memory bound issue, retry with a smaller file only.\n    return err\n}","preventionTips":["Bound recording size; chunk long audio into segments and transcribe per segment.","Monitor RSS during transcription to set limits with headroom."],"tags":["multipart","memory","elevenlabs","audio","go"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}