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

  1. 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
  2. Refresh the session (re-login) and retry the upload check
  3. If rate-limited, add backoff before requesting a new action token
  4. 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

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


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/493451aebdd17add. Report an issue: GitHub.