AlistGo/alist · error
failed to get action token: %w
Error message
failed to get action token: %w
What it means
Wrapped error from uploadCheck when getActionToken fails to mint an action token before calling /upload/check.php. The root cause is in the wrapped %w chain: either the underlying HTTP call to /user/get_action_token.php failed or it returned a non-Success result. Action tokens are short-lived authorization tokens distinct from the session token and are required for all upload operations.
Source
Thrown at drivers/mediafire/util.go:349
return resp.Response.Links[0].DirectDownload, nil
}
func (d *Mediafire) calculateSHA256(file *os.File) (string, error) {
hasher := sha256.New()
if _, err := file.Seek(0, 0); err != nil {
return "", err
}
if _, err := io.Copy(hasher, file); err != nil {
return "", err
}
return hex.EncodeToString(hasher.Sum(nil)), nil
}
func (d *Mediafire) uploadCheck(ctx context.Context, filename string, filesize int64, filehash, folderKey string) (*MediafireCheckResponse, error) {
actionToken, err := d.getActionToken(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get action token: %w", err)
}
query := map[string]string{
"session_token": actionToken, /* d.SessionToken */
"filename": filename,
"size": strconv.FormatInt(filesize, 10),
"hash": filehash,
"folder_key": folderKey,
"resumable": "yes",
"response_format": "json",
}
var resp MediafireCheckResponse
_, err = d.postForm("/upload/check.php", query, &resp)
if err != nil {
return nil, err
}
View on GitHub (pinned to 843d9dc814)
Solutions
- Inspect the wrapped error with errors.Unwrap / errors.As to see if it is the HTTP failure or the "MediaFire action token failed" result error
- Refresh the session (re-login) and retry the upload check
- If rate-limited, add backoff before requesting a new action token
- Cache action tokens for their lifespan (the code requests 1440 minutes) instead of minting one per call
Example fix
// before
actionToken, err := d.getActionToken(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get action token: %w", err)
}
// after (caller side: distinguish transient token failure from permanent one)
if _, err := d.uploadCheck(ctx, name, size, hash, folder); err != nil {
if strings.Contains(err.Error(), "action token") {
d.SessionToken = "" // force re-login on next call
}
return err
} Defensive patterns
Strategy: retry
Validate before calling
if d.SessionToken == "" {
return errors.New("mediafire session not initialized; call Init/login first")
} Try / catch
// Retry once after forced re-login, then surface the wrapped chain
if _, err := d.uploadCheck(...); err != nil {
var tokErr *erris
if strings.Contains(err.Error(), "action token") {
if rl := d.relogin(); rl == nil {
if _, err = d.uploadCheck(...); err == nil { return nil }
}
}
return fmt.Errorf("uploadCheck failed: %w", err)
} Prevention
- Cache action tokens with their expiry instead of minting per call
- Wrap token acquisition in a mutex so concurrent uploads share one token
- Monitor wrapped errors to distinguish HTTP vs Result failures
When it happens
Trigger: Expired or invalidated session_token (d.SessionToken) passed to get_action_token.php; MediaFire API outage or rate limiting on token issuance; account logged out remotely; action token request made with an action already in flight for a token type that cannot be reused.
Common situations: Long upload sessions where the cached session token expired; driver stored after re-login elsewhere; network interruption at the exact token request; MediaFire tightening token issuance for API version changes.
Related errors
- expected *os.File, got %T
- MediaFire upload check failed: %s
- failed to read response body: %v
- failed to parse response: %v
- resumable upload failed with status %d
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/493451aebdd17add.
Report an issue: GitHub.