{"record":{"id":"9452e09a6d00feba","repo":"dutchcoders/transfer.sh","slug":"internal-server-error","errorCode":null,"errorMessage":"Internal server error.","messagePattern":"Internal server error\\.","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"server/handlers.go","lineNumber":1015,"sourceCode":"\t\t\t}\n\n\t\t\ts.logger.Printf(\"%s\", err.Error())\n\t\t\thttp.Error(w, \"Could not retrieve file.\", http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\theader := &zip.FileHeader{\n\t\t\tName:   strings.Split(key, \"/\")[1],\n\t\t\tMethod: zip.Store,\n\n\t\t\tModified: time.Now().UTC(),\n\t\t}\n\n\t\tfw, err := zw.CreateHeader(header)\n\n\t\tif err != nil {\n\t\t\ts.logger.Printf(\"%s\", err.Error())\n\t\t\thttp.Error(w, \"Internal server error.\", http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\tif _, err = io.Copy(fw, reader); err != nil {\n\t\t\ts.logger.Printf(\"%s\", err.Error())\n\t\t\thttp.Error(w, \"Internal server error.\", http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t}\n\n\tif err := zw.Close(); err != nil {\n\t\ts.logger.Printf(\"%s\", err.Error())\n\t\thttp.Error(w, \"Internal server error.\", http.StatusInternalServerError)\n\t\treturn\n\t}\n}\n\nfunc (s *Server) tarGzHandler(w http.ResponseWriter, r *http.Request) {","sourceCodeStart":997,"sourceCodeEnd":1033,"githubUrl":"https://github.com/dutchcoders/transfer.sh/blob/c37bfd95797fd6da8a6da53fc13d191994b3f687/server/handlers.go#L997-L1033","documentation":"After building a zip.FileHeader, zipHandler calls zw.CreateHeader(header) to add an entry to the streaming zip. On failure the server responds with HTTP 500 'Internal server error.'. CreateHeader only fails in narrow cases — the underlying writer has already errored, or the header is invalid.","triggerScenarios":"zw.CreateHeader returns an error: the underlying HTTP response writer failed (client disconnected, connection reset), or the FileHeader name is invalid/empty (e.g. strings.Split(key, \"/\")[1] yielded an empty or malformed name).","commonSituations":"Client aborted the download mid-stream so ResponseWriter writes fail; filename derived from the storage key is empty or contains invalid zip path characters; zip64 limits approached for very large archives.","solutions":["Retry the download; if the client disconnected, this is expected and harmless — verify client connectivity.","Check the log line emitted with the 500 to distinguish header-name errors from write errors.","Sanitize/validate the entry name derived from the storage key before building the header.","Ensure no buffering middleware truncates the streamed response for large archives."],"exampleFix":"// before\nName: strings.Split(key, \"/\")[1],\n// after\nparts := strings.Split(key, \"/\")\nname := \"file\"\nif len(parts) > 1 && parts[1] != \"\" {\n    name = path.Base(parts[1])\n}\nheader := &zip.FileHeader{Name: name, Method: zip.Store}","handlingStrategy":"try-catch","validationCode":"// Validate the entry name before requesting the archive:\nname := path.Base(strings.SplitN(key, \"/\", 2)[1])\nif name == \"\" || strings.ContainsAny(name, \"\\\\\\x00\") {\n    // invalid zip entry name; fix the key naming scheme\n}","typeGuard":null,"tryCatchPattern":"// 500 during streaming usually means client disconnect; check logs to distinguish\n// header errors (fix name) from write errors (client/connection issue)","preventionTips":["Keep storage keys ASCII and path-safe so derived zip names are valid.","Keep clients connected: disable aggressive client timeouts for archive downloads.","Avoid middleware that buffers or truncates streaming zip responses.","For very large archives, watch for zip64 size limits."],"tags":["http-500","zip","streaming"],"backgroundTag":"zip-write-failed","analyzedSha":"c37bfd95797fd6da8a6da53fc13d191994b3f687","analyzedAt":"2026-09-05T10:21:07.548Z","contentChangedAt":"2026-09-05T10:21:07.548Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}