diff --git a/archive.go b/archive.go
index a437e88ae83b69a056a44941298e5eacce8231fe..b615c3c93e10ee4ebd47aaa86e69ecbc8c0f3d30 100644
--- a/archive.go
+++ b/archive.go
@@ -5,7 +5,6 @@ In this file we handle 'git archive' downloads
 package main
 
 import (
-	"errors"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -20,7 +19,8 @@ import (
 
 func handleGetArchive(w http.ResponseWriter, r *gitRequest) {
 	var format string
-	switch filepath.Base(r.URL.Path) {
+	urlPath := r.URL.Path
+	switch filepath.Base(urlPath) {
 	case "archive.zip":
 		format = "zip"
 	case "archive.tar":
@@ -30,7 +30,7 @@ func handleGetArchive(w http.ResponseWriter, r *gitRequest) {
 	case "archive.tar.bz2":
 		format = "tar.bz2"
 	default:
-		fail500(w, "handleGetArchive", errors.New("invalid archive format"))
+		fail500(w, fmt.Errorf("handleGetArchive: invalid format: %s", urlPath))
 	}
 
 	archiveFilename := path.Base(r.ArchivePath)
@@ -52,7 +52,7 @@ func handleGetArchive(w http.ResponseWriter, r *gitRequest) {
 	// to finalize the cached archive.
 	tempFile, err := prepareArchiveTempfile(path.Dir(r.ArchivePath), archiveFilename)
 	if err != nil {
-		fail500(w, "handleGetArchive create tempfile for archive", err)
+		fail500(w, fmt.Errorf("handleGetArchive: create tempfile: %v", err))
 	}
 	defer tempFile.Close()
 	defer os.Remove(tempFile.Name())
@@ -62,12 +62,12 @@ func handleGetArchive(w http.ResponseWriter, r *gitRequest) {
 	archiveCmd := gitCommand("", "git", "--git-dir="+r.RepoPath, "archive", "--format="+archiveFormat, "--prefix="+r.ArchivePrefix+"/", r.CommitId)
 	archiveStdout, err := archiveCmd.StdoutPipe()
 	if err != nil {
-		fail500(w, "handleGetArchive", err)
+		fail500(w, fmt.Errorf("handleGetArchive: archive stdout: %v", err))
 		return
 	}
 	defer archiveStdout.Close()
 	if err := archiveCmd.Start(); err != nil {
-		fail500(w, "handleGetArchive", err)
+		fail500(w, fmt.Errorf("handleGetArchive: start %v: %v", archiveCmd.Args, err))
 		return
 	}
 	defer cleanUpProcessGroup(archiveCmd) // Ensure brute force subprocess clean-up
@@ -80,13 +80,13 @@ func handleGetArchive(w http.ResponseWriter, r *gitRequest) {
 
 		stdout, err = compressCmd.StdoutPipe()
 		if err != nil {
-			fail500(w, "handleGetArchive compressCmd stdout pipe", err)
+			fail500(w, fmt.Errorf("handleGetArchive: compress stdout: %v", err))
 			return
 		}
 		defer stdout.Close()
 
 		if err := compressCmd.Start(); err != nil {
-			fail500(w, "handleGetArchive start compressCmd process", err)
+			fail500(w, fmt.Errorf("handleGetArchive: start %v: %v", compressCmd.Args, err))
 			return
 		}
 		defer compressCmd.Wait()
@@ -101,22 +101,22 @@ func handleGetArchive(w http.ResponseWriter, r *gitRequest) {
 	setArchiveHeaders(w, format, archiveFilename)
 	w.WriteHeader(200) // Don't bother with HTTP 500 from this point on, just return
 	if _, err := io.Copy(w, archiveReader); err != nil {
-		logContext("handleGetArchive read from subprocess", err)
+		log.Printf("handleGetArchive: read: %v", err)
 		return
 	}
 	if err := archiveCmd.Wait(); err != nil {
-		logContext("handleGetArchive wait for archiveCmd", err)
+		log.Printf("handleGetArchive: archiveCmd: %v", err)
 		return
 	}
 	if compressCmd != nil {
 		if err := compressCmd.Wait(); err != nil {
-			logContext("handleGetArchive wait for compressCmd", err)
+			log.Printf("handleGetArchive: compressCmd: %v", err)
 			return
 		}
 	}
 
 	if err := finalizeCachedArchive(tempFile, r.ArchivePath); err != nil {
-		logContext("handleGetArchive finalize cached archive", err)
+		log.Printf("handleGetArchive: finalize cached archive: %v", err)
 		return
 	}
 }
diff --git a/authorization.go b/authorization.go
index 42ef1f3b5898192cbf4bd9843c8bfa22576a0d01..8c8c0df91a08f0052e4e8a9f585591f0e7364edb 100644
--- a/authorization.go
+++ b/authorization.go
@@ -3,6 +3,7 @@ package main
 import (
 	"encoding/json"
 	"errors"
+	"fmt"
 	"io"
 	"net/http"
 	"strings"
@@ -12,13 +13,13 @@ func preAuthorizeHandler(handleFunc serviceHandleFunc, suffix string) serviceHan
 	return func(w http.ResponseWriter, r *gitRequest) {
 		authReq, err := r.u.newUpstreamRequest(r.Request, nil, suffix)
 		if err != nil {
-			fail500(w, "newUpstreamRequest", err)
+			fail500(w, fmt.Errorf("preAuthorizeHandler: newUpstreamRequest: %v", err))
 			return
 		}
 
 		authResponse, err := r.u.httpClient.Do(authReq)
 		if err != nil {
-			fail500(w, "doAuthRequest", err)
+			fail500(w, fmt.Errorf("preAuthorizeHandler: do %v: %v", authReq.URL.Path, err))
 			return
 		}
 		defer authResponse.Body.Close()
@@ -46,7 +47,7 @@ func preAuthorizeHandler(handleFunc serviceHandleFunc, suffix string) serviceHan
 		// request metadata. We must extract this information from the auth
 		// response body.
 		if err := json.NewDecoder(authResponse.Body).Decode(&r.authorizationResponse); err != nil {
-			fail500(w, "decode authorization response", err)
+			fail500(w, fmt.Errorf("preAuthorizeHandler: decode authorization response: %v", err))
 			return
 		}
 		// Don't hog a TCP connection in CLOSE_WAIT, we can already close it now
@@ -68,7 +69,7 @@ func preAuthorizeHandler(handleFunc serviceHandleFunc, suffix string) serviceHan
 func repoPreAuthorizeHandler(handleFunc serviceHandleFunc) serviceHandleFunc {
 	return preAuthorizeHandler(func(w http.ResponseWriter, r *gitRequest) {
 		if r.RepoPath == "" {
-			fail500(w, "repoPreAuthorizeHandler", errors.New("missing authorization response"))
+			fail500(w, errors.New("repoPreAuthorizeHandler: RepoPath empty"))
 			return
 		}
 
diff --git a/git-http.go b/git-http.go
index ebe631c330e42dd58933b30e4120a31a984f5bcf..99542073aa01d6b217529e42af66282d58ef410f 100644
--- a/git-http.go
+++ b/git-http.go
@@ -7,6 +7,7 @@ package main
 import (
 	"fmt"
 	"io"
+	"log"
 	"net/http"
 	"path/filepath"
 	"strings"
@@ -24,12 +25,12 @@ func handleGetInfoRefs(w http.ResponseWriter, r *gitRequest) {
 	cmd := gitCommand(r.GL_ID, "git", subCommand(rpc), "--stateless-rpc", "--advertise-refs", r.RepoPath)
 	stdout, err := cmd.StdoutPipe()
 	if err != nil {
-		fail500(w, "handleGetInfoRefs", err)
+		fail500(w, fmt.Errorf("handleGetInfoRefs: stdout: %v", err))
 		return
 	}
 	defer stdout.Close()
 	if err := cmd.Start(); err != nil {
-		fail500(w, "handleGetInfoRefs", err)
+		fail500(w, fmt.Errorf("handleGetInfoRefs: start %v: %v", cmd.Args, err))
 		return
 	}
 	defer cleanUpProcessGroup(cmd) // Ensure brute force subprocess clean-up
@@ -39,19 +40,19 @@ func handleGetInfoRefs(w http.ResponseWriter, r *gitRequest) {
 	w.Header().Add("Cache-Control", "no-cache")
 	w.WriteHeader(200) // Don't bother with HTTP 500 from this point on, just return
 	if err := pktLine(w, fmt.Sprintf("# service=%s\n", rpc)); err != nil {
-		logContext("handleGetInfoRefs response", err)
+		log.Printf("handleGetInfoRefs: pktLine: %v", err)
 		return
 	}
 	if err := pktFlush(w); err != nil {
-		logContext("handleGetInfoRefs response", err)
+		log.Printf("handleGetInfoRefs: pktFlush: %v", err)
 		return
 	}
 	if _, err := io.Copy(w, stdout); err != nil {
-		logContext("handleGetInfoRefs read from subprocess", err)
+		log.Printf("handleGetInfoRefs: read from %v: %v", cmd.Args, err)
 		return
 	}
 	if err := cmd.Wait(); err != nil {
-		logContext("handleGetInfoRefs wait for subprocess", err)
+		log.Printf("handleGetInfoRefs: wait for %v: %v", cmd.Args, err)
 		return
 	}
 }
@@ -63,7 +64,7 @@ func handlePostRPC(w http.ResponseWriter, r *gitRequest) {
 	action := filepath.Base(r.URL.Path)
 	if !(action == "git-upload-pack" || action == "git-receive-pack") {
 		// The 'dumb' Git HTTP protocol is not supported
-		fail500(w, "handlePostRPC", err)
+		fail500(w, fmt.Errorf("handlePostRPC: unsupported action: %s", r.URL.Path))
 		return
 	}
 
@@ -71,25 +72,25 @@ func handlePostRPC(w http.ResponseWriter, r *gitRequest) {
 	cmd := gitCommand(r.GL_ID, "git", subCommand(action), "--stateless-rpc", r.RepoPath)
 	stdout, err := cmd.StdoutPipe()
 	if err != nil {
-		fail500(w, "handlePostRPC", err)
+		fail500(w, fmt.Errorf("handlePostRPC: stdout: %v", err))
 		return
 	}
 	defer stdout.Close()
 	stdin, err := cmd.StdinPipe()
 	if err != nil {
-		fail500(w, "handlePostRPC", err)
+		fail500(w, fmt.Errorf("handlePostRPC: stdin: %v", err))
 		return
 	}
 	defer stdin.Close()
 	if err := cmd.Start(); err != nil {
-		fail500(w, "handlePostRPC", err)
+		fail500(w, fmt.Errorf("handlePostRPC: start %v: %v", cmd.Args, err))
 		return
 	}
 	defer cleanUpProcessGroup(cmd) // Ensure brute force subprocess clean-up
 
 	// Write the client request body to Git's standard input
 	if _, err := io.Copy(stdin, r.Body); err != nil {
-		fail500(w, "handlePostRPC write to subprocess", err)
+		fail500(w, fmt.Errorf("handlePostRPC write to %v: %v", cmd.Args, err))
 		return
 	}
 	// Signal to the Git subprocess that no more data is coming
@@ -106,11 +107,11 @@ func handlePostRPC(w http.ResponseWriter, r *gitRequest) {
 
 	// This io.Copy may take a long time, both for Git push and pull.
 	if _, err := io.Copy(w, stdout); err != nil {
-		logContext("handlePostRPC read from subprocess", err)
+		log.Printf("handlePostRPC read from %v:%v", cmd.Args, err)
 		return
 	}
 	if err := cmd.Wait(); err != nil {
-		logContext("handlePostRPC wait for subprocess", err)
+		log.Printf("handlePostRPC wait for %v: %v", err)
 		return
 	}
 }
diff --git a/handlers.go b/handlers.go
index f64309db5505beb1c780f933f87be4a24e3308c5..8e008800a398328b57e452719e7de82e6c8b9ed4 100644
--- a/handlers.go
+++ b/handlers.go
@@ -19,15 +19,15 @@ func contentEncodingHandler(handleFunc serviceHandleFunc) serviceHandleFunc {
 			body = r.Body
 		case "gzip":
 			body, err = gzip.NewReader(r.Body)
+			defer body.Close()
 		default:
 			err = fmt.Errorf("unsupported content encoding: %s", contentEncoding)
 		}
 
 		if err != nil {
-			fail500(w, "contentEncodingHandler", err)
+			fail500(w, fmt.Errorf("contentEncodingHandler: %v", err))
 			return
 		}
-		defer body.Close()
 
 		r.Body = body
 		r.Header.Del("Content-Encoding")
diff --git a/helpers.go b/helpers.go
index cbeab079e65293a02d30be76802882c2217ba492..52ff5bd7ebe54db1b808ff12706f192704fcd2a1 100644
--- a/helpers.go
+++ b/helpers.go
@@ -17,18 +17,14 @@ import (
 	"syscall"
 )
 
-func fail400(w http.ResponseWriter, context string, err error) {
+func fail400(w http.ResponseWriter, err error) {
 	http.Error(w, "Bad request", 400)
-	logContext(context, err)
+	log.Print(err)
 }
 
-func fail500(w http.ResponseWriter, context string, err error) {
+func fail500(w http.ResponseWriter, err error) {
 	http.Error(w, "Internal server error", 500)
-	logContext(context, err)
-}
-
-func logContext(context string, err error) {
-	log.Printf("%s: %v", context, err)
+	log.Print(err)
 }
 
 // Git subprocess helpers
diff --git a/lfs.go b/lfs.go
index 025dfff54ac0c56356c182fa72880f49b05a5edb..44638b21185bd49a8a39d8f8dc014ee8ed112e3c 100644
--- a/lfs.go
+++ b/lfs.go
@@ -8,6 +8,7 @@ import (
 	"crypto/sha256"
 	"encoding/hex"
 	"errors"
+	"fmt"
 	"io"
 	"io/ioutil"
 	"net/http"
@@ -15,31 +16,21 @@ import (
 	"path/filepath"
 )
 
-var (
-	errHashMismatch = errors.New("Content hash does not match OID")
-	errSizeMismatch = errors.New("Content size does not match")
-)
-
 func lfsAuthorizeHandler(handleFunc serviceHandleFunc) serviceHandleFunc {
 	return preAuthorizeHandler(func(w http.ResponseWriter, r *gitRequest) {
 
 		if r.StoreLFSPath == "" {
-			fail500(w, "lfsAuthorizeHandler", errors.New("Don't know where to store object, no store path specified."))
+			fail500(w, errors.New("lfsAuthorizeHandler: StoreLFSPath empty"))
 			return
 		}
 
 		if r.LfsOid == "" {
-			fail500(w, "lfsAuthorizeHandler", errors.New("Lfs object oid not specified."))
-			return
-		}
-
-		if r.LfsSize == 0 {
-			fail500(w, "lfsAuthorizeHandler", errors.New("Lfs object size not specified."))
+			fail500(w, errors.New("lfsAuthorizeHandler: LfsOid empty"))
 			return
 		}
 
 		if err := os.MkdirAll(r.StoreLFSPath, 0700); err != nil {
-			fail500(w, "Couldn't create directory for storing LFS tmp objects.", err)
+			fail500(w, fmt.Errorf("lfsAuthorizeHandler: mkdir StoreLFSPath: %v", err))
 			return
 		}
 
@@ -50,7 +41,7 @@ func lfsAuthorizeHandler(handleFunc serviceHandleFunc) serviceHandleFunc {
 func handleStoreLfsObject(w http.ResponseWriter, r *gitRequest) {
 	file, err := ioutil.TempFile(r.StoreLFSPath, r.LfsOid)
 	if err != nil {
-		fail500(w, "Couldn't open tmp file for writing.", err)
+		fail500(w, fmt.Errorf("handleStoreLfsObject: create tempfile: %v", err))
 		return
 	}
 	defer os.Remove(file.Name())
@@ -61,32 +52,32 @@ func handleStoreLfsObject(w http.ResponseWriter, r *gitRequest) {
 
 	written, err := io.Copy(hw, r.Body)
 	if err != nil {
-		fail500(w, "Failed to save received LFS object.", err)
+		fail500(w, fmt.Errorf("handleStoreLfsObject: write tempfile: %v", err))
 		return
 	}
 	file.Close()
 
 	if written != r.LfsSize {
-		fail500(w, "Inconsistent size: ", errSizeMismatch)
+		fail500(w, fmt.Errorf("handleStoreLfsObject: expected size %d, wrote %d", r.LfsSize, written))
 		return
 	}
 
 	shaStr := hex.EncodeToString(hash.Sum(nil))
 	if shaStr != r.LfsOid {
-		fail500(w, "Inconsistent size: ", errSizeMismatch)
+		fail500(w, fmt.Errorf("handleStoreLfsObject: expected sha256 %s, got %s", r.LfsOid, shaStr))
 		return
 	}
 	r.Header.Set("X-GitLab-Lfs-Tmp", filepath.Base(file.Name()))
 
 	storeReq, err := r.u.newUpstreamRequest(r.Request, nil, "")
 	if err != nil {
-		fail500(w, "newUpstreamRequestLfsStoreCallback", err)
+		fail500(w, fmt.Errorf("handleStoreLfsObject: newUpstreamRequest: %v", err))
 		return
 	}
 
 	storeResponse, err := r.u.httpClient.Do(storeReq)
 	if err != nil {
-		fail500(w, "doRequestLfsStoreCallback", err)
+		fail500(w, fmt.Errorf("handleStoreLfsObject: do %v: %v", storeReq.URL.Path, err))
 		return
 	}
 	defer storeResponse.Body.Close()
diff --git a/proxy.go b/proxy.go
index 36079de0984a9cb77ec7fecff24326958e09d986..4605b827b01f95cb44f71fd0da715c80f8851d73 100644
--- a/proxy.go
+++ b/proxy.go
@@ -1,19 +1,20 @@
 package main
 
 import (
+	"fmt"
 	"net/http"
 )
 
 func proxyRequest(w http.ResponseWriter, r *gitRequest) {
 	upRequest, err := r.u.newUpstreamRequest(r.Request, r.Body, "")
 	if err != nil {
-		fail500(w, "newUpstreamRequest", err)
+		fail500(w, fmt.Errorf("proxyRequest: newUpstreamRequest: %v", err))
 		return
 	}
 
 	upResponse, err := r.u.httpClient.Do(upRequest)
 	if err != nil {
-		fail500(w, "do upstream request", err)
+		fail500(w, fmt.Errorf("proxyRequest: do %v: %v", upRequest.URL.Path, err))
 		return
 	}
 	defer upResponse.Body.Close()
diff --git a/uploads.go b/uploads.go
index 81cfb1ee624d51484bdc7be74a332950e4ae8fb2..37c1fd90b6337660e7b4998c9a220e5da43c6e35 100644
--- a/uploads.go
+++ b/uploads.go
@@ -3,6 +3,7 @@ package main
 import (
 	"bytes"
 	"errors"
+	"fmt"
 	"io"
 	"io/ioutil"
 	"mime/multipart"
@@ -84,7 +85,7 @@ func rewriteFormFilesFromMultipart(r *gitRequest, writer *multipart.Writer) (cle
 
 func handleFileUploads(w http.ResponseWriter, r *gitRequest) {
 	if r.TempPath == "" {
-		fail500(w, "handleUploadFile", errors.New("missing temporary path"))
+		fail500(w, errors.New("handleFileUploads: TempPath empty"))
 		return
 	}
 
@@ -98,7 +99,7 @@ func handleFileUploads(w http.ResponseWriter, r *gitRequest) {
 		if err == http.ErrNotMultipart {
 			proxyRequest(w, r)
 		} else {
-			fail500(w, "Couldn't handle upload request.", err)
+			fail500(w, fmt.Errorf("handleFileUploads: extract files from multipart: %v", err))
 		}
 		return
 	}
@@ -113,7 +114,7 @@ func handleFileUploads(w http.ResponseWriter, r *gitRequest) {
 	// Create request
 	upstreamRequest, err := r.u.newUpstreamRequest(r.Request, nil, "")
 	if err != nil {
-		fail500(w, "Couldn't handle artifacts upload request.", err)
+		fail500(w, fmt.Errorf("handleFileUploads: newUpstreamRequest: %v", err))
 		return
 	}
 
@@ -125,7 +126,7 @@ func handleFileUploads(w http.ResponseWriter, r *gitRequest) {
 	// Forward request to backend
 	upstreamResponse, err := r.u.httpClient.Do(upstreamRequest)
 	if err != nil {
-		fail500(w, "do upstream request", err)
+		fail500(w, fmt.Errorf("handleFileUploads: do request %v", upstreamRequest.URL.Path, err))
 		return
 	}
 	defer upstreamResponse.Body.Close()
diff --git a/xsendfile.go b/xsendfile.go
index 88e3e51dcb39a5dc386335db7d160cc455cd1eb9..6f72a6b43620420c86829281c72adbb4847c8ea2 100644
--- a/xsendfile.go
+++ b/xsendfile.go
@@ -7,6 +7,7 @@ via the X-Sendfile mechanism. All that is needed in the Rails code is the
 package main
 
 import (
+	"fmt"
 	"io"
 	"log"
 	"net/http"
@@ -16,7 +17,7 @@ import (
 func handleSendFile(w http.ResponseWriter, r *gitRequest) {
 	upRequest, err := r.u.newUpstreamRequest(r.Request, r.Body, "")
 	if err != nil {
-		fail500(w, "newUpstreamRequest", err)
+		fail500(w, fmt.Errorf("handleSendFile: newUpstreamRequest: %v", err))
 		return
 	}
 
@@ -24,7 +25,7 @@ func handleSendFile(w http.ResponseWriter, r *gitRequest) {
 	upResponse, err := r.u.httpClient.Do(upRequest)
 	r.Body.Close()
 	if err != nil {
-		fail500(w, "do upstream request", err)
+		fail500(w, fmt.Errorf("handleSendfile:do upstream request: %v", err))
 		return
 	}
 
@@ -45,7 +46,7 @@ func handleSendFile(w http.ResponseWriter, r *gitRequest) {
 
 		// Copy body from Rails upResponse
 		if _, err := io.Copy(w, upResponse.Body); err != nil {
-			fail500(w, "Couldn't finalize X-File download request.", err)
+			fail500(w, fmt.Errorf("handleSendFile: copy upstream response: %v", err))
 		}
 		return
 	}
@@ -54,14 +55,14 @@ func handleSendFile(w http.ResponseWriter, r *gitRequest) {
 	upResponse.Body.Close()
 	content, err := os.Open(sendfile)
 	if err != nil {
-		fail500(w, "open sendfile", err)
+		fail500(w, fmt.Errorf("handleSendile: open sendfile: %v", err))
 		return
 	}
 	defer content.Close()
 
 	fi, err := content.Stat()
 	if err != nil {
-		fail500(w, "xSendFile get mtime", err)
+		fail500(w, fmt.Errorf("handleSendfile: get mtime: %v", err))
 		return
 	}
 	http.ServeContent(w, r.Request, "", fi.ModTime(), content)