{"record":{"id":"c6537b09443088c5","repo":"Billionmail/BillionMail","slug":"failed-to-create-zip-entry-for-s-v","errorCode":null,"errorMessage":"failed to create zip entry for %s: %v","messagePattern":"failed to create zip entry for (.+?): (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/controller/contact/contact_v1_export_contacts.go","lineNumber":217,"sourceCode":"}\n\n// ExportFile Export file information\ntype ExportFile struct {\n\tName     string // File name\n\tContent  string // File content\n\tContacts int    // Contact count\n}\n\n// createZipFileInMemory creates a ZIP file in memory\nfunc createZipFileInMemory(files []ExportFile) ([]byte, error) {\n\tvar buf bytes.Buffer\n\tzipWriter := zip.NewWriter(&buf)\n\n\tfor _, file := range files {\n\t\t// Create zip entry\n\t\tzipEntry, err := zipWriter.Create(file.Name)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to create zip entry for %s: %v\", file.Name, err)\n\t\t}\n\n\t\t// Write file content to zip\n\t\t_, err = zipEntry.Write([]byte(file.Content))\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to write content to zip for %s: %v\", file.Name, err)\n\t\t}\n\t}\n\n\terr := zipWriter.Close()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to close zip writer: %v\", err)\n\t}\n\n\treturn buf.Bytes(), nil\n}\n\n// exportContactsToCSV exports contacts to CSV format","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/controller/contact/contact_v1_export_contacts.go#L199-L235","documentation":"createZipFileInMemory builds a ZIP in memory using archive/zip. zipWriter.Create(name) returns a writer for a new entry; it fails when the archive writer is in a bad state (e.g. it was already closed) or the entry name is invalid for the ZIP format. This wrapper adds the offending file name to the error.","triggerScenarios":"Calling createZipFileInMemory with a file whose Name cannot be used as a ZIP entry name (e.g. invalid UTF-8 in the name), or reusing/closing the zip.Writer across calls and then creating another entry; in practice with this code, a fresh zip.Writer only fails on malformed entry names.","commonSituations":"Group names with control or non-UTF-8 characters flowing into ExportFile.Name; code refactors that close the writer per entry; concurrent use of a single zip.Writer (not goroutine-safe).","solutions":["Sanitize ExportFile.Name before building the ZIP (strip control characters, ensure valid UTF-8, reasonable length).","Use errors.Is/As or %w wrapping to preserve the underlying cause for diagnostics.","Ensure zipWriter.Close() is called exactly once, after all entries are written.","For special characters in group names, set zipWriter's flags or normalize names to ASCII.","If creating entries concurrently, serialize the calls — archive/zip.Writer is not safe for concurrent use."],"exampleFix":"// before\nzipEntry, err := zipWriter.Create(file.Name)\nif err != nil {\n    return nil, fmt.Errorf(\"failed to create zip entry for %s: %v\", file.Name, err)\n}\n// after\nsafeName := strings.Map(func(r rune) rune {\n    if r < 32 || r == 127 {\n        return -1\n    }\n    return r\n}, file.Name)\nzipEntry, err := zipWriter.Create(safeName)\nif err != nil {\n    return nil, fmt.Errorf(\"failed to create zip entry for %q: %w\", safeName, err)\n}","handlingStrategy":"validation","validationCode":"func safeZipName(name string) string {\n    name = strings.TrimSpace(name)\n    if !utf8.ValidString(name) { name = strings.ToValidUTF8(name, \"_\") }\n    name = strings.Map(func(r rune) rune { if r < 32 || r == 127 { return -1 }; return r }, name)\n    if name == \"\" { name = \"export.csv\" }\n    return name\n}\n// apply to each ExportFile.Name before createZipFileInMemory","typeGuard":null,"tryCatchPattern":"out, err := createZipFileInMemory(files)\nif err != nil {\n    var zerr *zip.Error\n    if errors.As(err, &zerr) {\n        return fmt.Errorf(\"zip export failed (%v); check file names\", zerr)\n    }\n    return fmt.Errorf(\"export failed: %w\", err)\n}","preventionTips":["Sanitize entry names: no control chars, valid UTF-8, reasonable length","Never reuse or close the zip.Writer between Create calls","Serialize zip.Writer usage — it is not concurrency-safe","Add a test that exports group names containing unicode/special characters"],"tags":["zip","archive","export"],"backgroundTag":"zip-entry-create-failed","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}