{"record":{"id":"7289d05be78361cc","repo":"sipeed/picoclaw","slug":"failed-to-create-form-file-w","errorCode":null,"errorMessage":"failed to create form file: %w","messagePattern":"failed to create form file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/audio/asr/elevenlabs_transcriber.go","lineNumber":74,"sourceCode":"\n\tfileInfo, err := audioFile.Stat()\n\tif err != nil {\n\t\tlogger.ErrorCF(\"voice\", \"Failed to get file info\", map[string]any{\"path\": audioFilePath, \"error\": err})\n\t\treturn nil, fmt.Errorf(\"failed to get file info: %w\", err)\n\t}\n\n\tlogger.DebugCF(\"voice\", \"Audio file details\", map[string]any{\n\t\t\"size_bytes\": fileInfo.Size(),\n\t\t\"file_name\":  filepath.Base(audioFilePath),\n\t})\n\n\tvar requestBody bytes.Buffer\n\twriter := multipart.NewWriter(&requestBody)\n\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)","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/audio/asr/elevenlabs_transcriber.go#L56-L92","documentation":"Thrown when multipart.Writer.CreateFormFile(\"file\", filepath.Base(audioFilePath)) fails while building the ElevenLabs upload. CreateFormFile writes a part header to a bytes.Buffer, so it only fails if the filename cannot be encoded into the Content-Disposition header (invalid characters) or the buffer write fails. Practically a configuration-of-input error, not a runtime one.","triggerScenarios":"The base filename contains characters the multipart header writer rejects, e.g. CR/LF, quotes, or non-UTF-8 bytes; otherwise only an out-of-memory condition on bytes.Buffer triggers it.","commonSituations":"Recordings named with embedded newlines or control characters (buggy recorder using a timestamp format with \\n); filenames from another OS with invalid byte sequences.","solutions":["Sanitize the filename before transcription: strip control characters and keep an ASCII-safe base name.","Reproduce by logging filepath.Base(audioFilePath) and checking for hidden \\r/\\n/non-UTF-8 bytes.","If it happens without odd filenames, suspect memory pressure and profile the process."],"exampleFix":"// before\npart, err := writer.CreateFormFile(\"file\", filepath.Base(audioFilePath))\n\n// after (sanitize at the call site)\nname := strings.Map(func(r rune) rune {\n    if r < 32 || r == 127 || r == '\"' { return -1 }\n    return r\n}, filepath.Base(audioFilePath))\npart, err := writer.CreateFormFile(\"file\", name)","handlingStrategy":"validation","validationCode":"func safePartName(path string) (string, error) {\n    name := filepath.Base(path)\n    if !utf8.ValidString(name) || strings.ContainsAny(name, \"\\\"\\r\\n\\\\\") {\n        return \"\", fmt.Errorf(\"unsafe audio filename %q\", name)\n    }\n    return name, nil\n}","typeGuard":"func hasControlChars(s string) bool {\n    return strings.IndexFunc(s, func(r rune) bool { return r < 32 || r == 127 }) >= 0\n}","tryCatchPattern":"if _, err := el.Transcribe(ctx, path); err != nil && strings.Contains(err.Error(), \"failed to create form file\") {\n    return fmt.Errorf(\"audio filename rejected (%q): rename the file and retry\", filepath.Base(path))\n}","preventionTips":["Generate recording filenames yourself: timestamp + fixed extension, no user input.","Reject non-UTF-8 or control-character filenames at intake."],"tags":["multipart","filename","elevenlabs","audio","go"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}