GopeedLab/gopeed · error
blob source revoked
Error message
blob source revoked
What it means
Returned when a blob source still exists in the map but is marked revoked. Registry.get checks src.revoked (registry.go:626-631), and Source.acquireTask/releaseTask return it directly (registry.go:403-405,420-422). Revocation is how the registry retires a source: explicit Revoke, the final task Release, expiry of an unclaimed session-backed source after unclaimedSourceTTL (10 minutes), or Registry.Close.
Source
Thrown at internal/blob/registry.go:33
"strconv"
"strings"
"sync"
"time"
)
const urlPathPrefix = "/__blob/"
const rangeSourceFailureLimit = 2
// unclaimedSourceTTL bounds how long a session-backed source may keep its
// engine alive without ever being claimed by a download task.
var unclaimedSourceTTL = 10 * time.Minute
var (
ErrInvalidURL = errors.New("invalid blob url")
ErrInvalidOptions = errors.New("invalid blob options")
ErrSourceNotFound = errors.New("blob source not found")
ErrSourceRevoked = errors.New("blob source revoked")
ErrSourceClosed = errors.New("blob source closed")
ErrRangeNotAllowed = errors.New("blob range not allowed")
)
type SessionRef interface {
Retain()
Release()
}
type OpenRequest struct {
Offset int64
End int64
}
type OpenFunc func(ctx context.Context, req OpenRequest) (io.ReadCloser, error)
type CreateOptions struct {
ContentType stringView on GitHub (pinned to 7b7327ffb3)
Solutions
- Consider the source dead: create a new one and rebind the task's URL
- Acquire the source before starting the download task, not after, so the unclaimed TTL timer is cancelled (acquireTask stops it)
- Avoid re-using a blob URL after you have called Release for its last reference or Revoke
- If seen right after shutdown starts, it is benign racing with Registry.Close — skip the operation instead of retrying
Example fix
// before
_ = registry.Release(blobURL)
err := registry.Acquire(blobURL) // ErrSourceRevoked
// after
_ = registry.Release(blobURL)
blobURL, err = registry.CreateOpener(open, opts) // fresh source, fresh URL
if err != nil { return err }
err = registry.Acquire(blobURL) Defensive patterns
Strategy: try-catch
Try / catch
if err := registry.Acquire(blobURL); err != nil {
if errors.Is(err, blob.ErrSourceRevoked) {
// source was revoked (Revoke/final Release/TTL/Close): recreate it
blobURL, err = registry.CreateOpener(open, opts)
if err != nil { return err }
}
} Prevention
- Cancel the unclaimed TTL by Acquiring before the download starts, not after
- Treat Revoke and final Release as terminal events; drop all cached references to the URL
- During shutdown, ignore blob errors after calling Registry.Close
When it happens
Trigger: Calling Acquire/Release after Revoke(blobURL); calling Release for the last task reference and then any further blob operation on the same URL; creating a session-backed source and Acquiring it more than 10 minutes after creation; any blob call racing with Registry.Close (Close marks every source revoked).
Common situations: Extension/UI code holding onto a blob URL after the download finished (final Release already revoked it); revoking a source on cancel but a queued re-try path still referencing the old URL; slow test suites exceeding the 10-minute TTL between CreateOpener and Acquire.
Related errors
- blob source not found
- invalid blob url
- blob source closed
- invalid blob options
- cannot change ed2k target path after transfer started
AI-assisted analysis of GopeedLab/gopeed@7b7327ffb3 (2026-08-16).
Data as JSON: /api/errors/6044ea3df79d5da5.
Report an issue: GitHub.