-
-
Notifications
You must be signed in to change notification settings - Fork 6k
Description
Description
Summary
.tar.gz
files (as small as 12MB) fail to download from Gitea release pages due to HTTP Range Request handling issues. The download succeeds initially (206 Partial Content) but immediately fails on subsequent chunks with "context canceled" error, resulting in 401 Unauthorized responses.
Environment
- Gitea Version: v1.24.2-rootless
- Platform: Kubernetes (EKS 1.32)
- Deployment: Helm chart
- Database: PostgreSQL HA
- Cache: Valkey (Redis compatible)
- Load Balancer: AWS NLB with SSL termination
- Authentication: Username/Password (no OAuth)
Expected Behavior
.tar.gz
files should download completely without interruption when accessed through release download URLs, regardless of size.
Actual Behavior
- Browser initiates HTTP Range Request for
.tar.gz
files (12MB in this case) - First chunk downloads successfully (206 Partial Content, ~190ms)
- Within 10-30ms, subsequent chunk requests fail with "context canceled"
- Session verification fails → 401 Unauthorized response (~7ms)
- Download fails in browser with "Network Error"
- Multiple retries eventually succeed (sometimes after 3-5 minutes)
Reproduction Steps
- Create a release with a
.tar.gz
file (12MB in this case) - Navigate to release page in Chrome/Edge browser
- Click download link for
.tar.gz
file - Observe download failure in browser
- Check Gitea logs for "GetUserByID: context canceled" errors
Log Evidence
Pattern 1: First failure (07:59:01)
2025年08月18日T07:59:01.290779720Z gitea 2025年08月18日 07:59:01 HTTPRequest [I] router: completed GET /OrgName/repo_name/releases/download/v1.0.35/build-artifacts-v1.0.35.tar.gz for 10.0.0.1:18329, 206 Partial Content in 192.5ms @ repo/repo.go:318(repo.RedirectDownload)
2025年08月18日T07:59:01.320181025Z gitea 2025年08月18日 07:59:01 services/auth/session.go:51:(*Session).Verify() [E] GetUserByID: context canceled
2025年08月18日T07:59:01.320228848Z gitea 2025年08月18日 07:59:01 routers/web/web.go:121:Routes.webAuth.10() [E] Failed to verify user: context canceled
2025年08月18日T07:59:01.322235910Z gitea 2025年08月18日 07:59:01 HTTPRequest [I] router: completed GET /OrgName/repo_name/releases/download/v1.0.35/build-artifacts-v1.0.35.tar.gz for 10.0.0.1:18329, 401 Unauthorized in 6.8ms @ web/web.go:118(web.Routes.webAuth)
Pattern 2: Second retry failure (07:59:12)
2025年08月18日T07:59:12.250175593Z gitea 2025年08月18日 07:59:12 HTTPRequest [I] router: completed GET /OrgName/repo_name/releases/download/v1.0.35/build-artifacts-v1.0.35.tar.gz for 10.0.0.2:57323, 206 Partial Content in 193.7ms @ repo/repo.go:318(repo.RedirectDownload)
2025年08月18日T07:59:12.262348544Z gitea 2025年08月18日 07:59:12 services/auth/session.go:51:(*Session).Verify() [E] GetUserByID: context canceled
2025年08月18日T07:59:12.262387879Z gitea 2025年08月18日 07:59:12 routers/web/web.go:121:Routes.webAuth.10() [E] Failed to verify user: context canceled
2025年08月18日T07:59:12.264366790Z gitea 2025年08月18日 07:59:12 HTTPRequest [I] router: completed GET /OrgName/repo_name/releases/download/v1.0.35/build-artifacts-v1.0.35.tar.gz for 10.0.0.2:57323, 401 Unauthorized in 6.8ms @ web/web.go:118(web.Routes.webAuth)
Pattern 3: Third retry failure (08:01:17)
2025年08月18日T08:01:17.477449999Z gitea 2025年08月18日 08:01:17 HTTPRequest [I] router: completed GET /OrgName/repo_name/releases/download/v1.0.35/build-artifacts-v1.0.35.tar.gz for 10.0.0.3:3633, 206 Partial Content in 189.9ms @ repo/repo.go:318(repo.RedirectDownload)
2025年08月18日T08:01:17.488702742Z gitea 2025年08月18日 08:01:17 services/auth/session.go:51:(*Session).Verify() [E] GetUserByID: context canceled
2025年08月18日T08:01:17.488750103Z gitea 2025年08月18日 08:01:17 routers/web/web.go:121:Routes.webAuth.10() [E] Failed to verify user: context canceled
2025年08月18日T08:01:17.491089433Z gitea 2025年08月18日 08:01:17 HTTPRequest [I] router: completed GET /OrgName/repo_name/releases/download/v1.0.35/build-artifacts-v1.0.35.tar.gz for 10.0.0.3:3633, 401 Unauthorized in 6.6ms @ web/web.go:118(web.Routes.webAuth)
Pattern 4: Final success (08:03:06)
In this case, Browser switches from Range Request (206 Partial Content) to normal download (200 OK) and succeeds. Subsequent requests are cached (304 Not Modified).
2025年08月18日T08:03:06.000000000Z gitea 2025年08月18日 08:03:06 HTTPRequest [I] router: completed GET /OrgName/repo_name/releases/download/v1.0.35/build-artifacts-v1.0.35.tar.gz for 10.0.0.1:46502, 200 OK in 1051.9ms @ repo/repo.go:318(repo.RedirectDownload)
2025年08月18日T08:03:47.000000000Z gitea 2025年08月18日 08:03:47 HTTPRequest [I] router: completed GET /OrgName/repo_name/releases/download/v1.0.35/build-artifacts-v1.0.35.tar.gz for 10.0.0.2:24190, 304 Not Modified in 193.4ms @ repo/repo.go:318(repo.RedirectDownload)
2025年08月18日T08:04:33.000000000Z gitea 2025年08月18日 08:04:33 HTTPRequest [I] router: completed GET /OrgName/repo_name/releases/download/v1.0.35/build-artifacts-v1.0.35.tar.gz for 10.0.0.2:24190, 304 Not Modified in 196.4ms @ repo/repo.go:318(repo.RedirectDownload)
HTTP Request Type Analysis
Range Request vs Normal Request identification:
-
Range Request (partial download): Response code
206 Partial Content
- Browser sends
Range: bytes=0-1048575
header - Server responds with partial file content
- Used by browsers for large files to enable resume capability
- Browser sends
-
Normal Request (full download): Response code
200 OK
- No Range header sent
- Server responds with complete file
- Traditional single-request download
Failure Pattern: 206 Partial Content
→ context canceled
→ 401 Unauthorized
Success Pattern: 200 OK
(browser fallback to normal download after Range Request failures)
Timeline Summary
07:59:01 - tar.gz download failure (Range Request: 206 Partial Content → 401 Unauthorized)
07:59:12 - tar.gz retry failure (Range Request: 206 Partial Content → 401 Unauthorized)
08:01:17 - tar.gz download failure (Range Request: 206 Partial Content → 401 Unauthorized)
08:03:06 - tar.gz download success (Normal Request: 200 OK, 1051ms)
08:03:47~08:04:33 - cached responses (304 Not Modified)
Key observations:
- Consistent timing: Each failure follows the same pattern - 206 response (~190ms) → context canceled (~10ms later) → 401 response (~7ms)
- Different client IPs: 10.0.0.1, 10.0.0.2, 10.0.0.3 (indicating different browser sessions/connections)
- Eventually succeeds: After multiple failures, download works with 200 OK status
Root Cause Analysis
The issue appears to be in the session verification middleware at services/auth/session.go:51
.
Sequence of events:
- Browser sends Range Request:
Range: bytes=0-1048575
- Gitea responds with 206 Partial Content (first chunk)
- Browser immediately sends next Range Request:
Range: bytes=1048576-2097151
- Problem: The HTTP context from the first request is already canceled
GetUserByID
is called with canceled context → "context canceled" error- Session verification fails → 401 Unauthorized
Why only .tar.gz
files?
- Browser automatically uses Range Requests for compressed files (even as small as 12MB)
- ZIP files may have different MIME handling
- Other file types may not trigger Range Request behavior
Root cause hypothesis:
Gitea appears to prematurely terminate the HTTP context after responding to the first HTTP Range Request chunk (206 Partial Content), causing subsequent Range Request chunks to fail session verification when GetUserByID
is called with an already-canceled context. This context lifecycle management issue specifically affects HTTP Range Request handling, explaining why normal requests (200 OK) succeed while Range Requests consistently fail at the session middleware level.
Affected Code
The error occurs in session verification:
// services/auth/session.go:51 user, err := user_model.GetUserByID(ctx, sess.Get("uid").(int64)) if err != nil { // Return the err as-is to keep current signed-in session, in case the err is something like context.Canceled if !user_model.IsErrUserNotExist(err) { log.Error("GetUserByID: %v", err) // ← This logs "context canceled" return nil, err } }
Additional Context
- Issue is specific to rootless Gitea image
- Problem occurs with NLB direct access (no ingress controller)
- Related to context lifecycle management in HTTP Range Request handling
- Multiple successful downloads eventually work after retries
Related Issues
This appears to be related to but distinct from:
- Don't show context cancelled errors in attribute reader #19006 (Context cancelled error logging)
- Stop logging CheckPath returns error: context canceled #21064 (Context canceled logging)
- Wrong session auth handler order #34174 (Session auth handler order)
- Add context support for GetUserByID #17602 (Context support for GetUserByID)
The specific combination of HTTP Range Request + Context Cancellation + Session Verification seems to be a unique case not covered by existing issues.
Suggested Fix
Consider implementing proper context handling for HTTP Range Requests in the session verification middleware, ensuring that each Range Request gets its own valid context rather than inheriting a potentially canceled context from previous requests.
Gitea Version
v1.24.2-rootless
Can you reproduce the bug on the Gitea demo site?
No
Log Gist
No response
Screenshots
No response
Git Version
No response
Operating System
Amazon Linux 2023年8月20日250721 (amd64)
How are you running Gitea?
Official gitea helm chart v12.3.1 on EKS v1.32
Database
PostgreSQL