{"record":{"id":"07842c5615f118bd","repo":"sipeed/picoclaw","slug":"failed-to-copy-audio-data-w","errorCode":null,"errorMessage":"failed to copy audio data: %w","messagePattern":"failed to copy audio data: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/audio/asr/whisper_transcriber.go","lineNumber":160,"sourceCode":"\t\treturn nil, fmt.Errorf(\"failed to open audio file %s: %w\", audioFilePath, err)\n\t}\n\tdefer audioFile.Close()\n\n\tfileInfo, err := audioFile.Stat()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to stat audio file %s: %w\", audioFilePath, err)\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\treturn nil, fmt.Errorf(\"failed to create form file: %w\", err)\n\t}\n\n\tif _, copyErr := io.Copy(part, audioFile); copyErr != nil {\n\t\treturn nil, fmt.Errorf(\"failed to copy audio data: %w\", copyErr)\n\t}\n\n\tif err = writer.WriteField(\"model\", t.modelID); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to write model field: %w\", err)\n\t}\n\n\tif err = writer.WriteField(\"response_format\", \"json\"); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to write response_format field: %w\", err)\n\t}\n\n\tif err = writer.Close(); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to close multipart writer: %w\", err)\n\t}\n\n\treturn t.doRequest(ctx, &requestBody, writer.FormDataContentType(), fileInfo.Size())\n}\n\nfunc (t *WhisperTranscriber) doRequest(","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/audio/asr/whisper_transcriber.go#L142-L178","documentation":"Returned by WhisperTranscriber.Transcribe when io.Copy fails while streaming the opened audio file into the multipart part. The destination is an in-memory bytes.Buffer that does not error, so the failure comes from reading audioFile itself: I/O errors on disk or network mounts, or the file being truncated/deleted between os.Open and the copy. Wrapped with %w.","triggerScenarios":"The audio temp file is deleted by a concurrent cleanup routine after os.Open but before or during io.Copy; reading from an NFS/FUSE mount that returns EIO/ESTALE; a truncated or zero-byte recording; hardware read errors.","commonSituations":"Voice pipelines where the temp WAV/OGG is removed by a race with the recorder; files on network storage; long-lived processes where the file disappears between open and upload.","solutions":["Retry the transcription once — transient read errors usually clear","Read the file fully into memory right after validating it and use TranscribeData to remove the open-to-copy window","Make temp-file cleanup age-based (only delete files older than e.g. 1h) so in-flight files survive","Check disk and mount health if errors persist"],"exampleFix":"// before\nresp, err := transcriber.Transcribe(ctx, audioPath)\n// after\ndata, err := os.ReadFile(audioPath)\nif err != nil {\n    return nil, fmt.Errorf(`read audio: %w`, err)\n}\nresp, err := transcriber.TranscribeData(ctx, data, filepath.Base(audioPath))","handlingStrategy":"retry","validationCode":"data, err := os.ReadFile(audioPath)\nif err != nil {\n    return err\n}\nif len(data) == 0 {\n    return errors.New(`refusing to transcribe empty audio file`)\n}\n// pass data to TranscribeData to remove the open-to-copy race window","typeGuard":"func isPathReadFailure(err error) bool {\n    var perr *fs.PathError\n    return errors.As(err, &perr)\n}","tryCatchPattern":"if err != nil {\n    var perr *fs.PathError\n    if errors.As(err, &perr) {\n        // file vanished or read failed mid-copy: re-read once (or re-record), then surface\n    }\n}","preventionTips":["Delete temp audio by age (e.g. older than 1h), never in-flight files","Read the whole file up front (os.ReadFile) and use TranscribeData","Log file size at open and bytes copied to detect truncation races"],"tags":["io","filesystem","race-condition","whisper","asr"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}