{"record":{"id":"493451aebdd17add","repo":"AlistGo/alist","slug":"failed-to-get-action-token-w","errorCode":null,"errorMessage":"failed to get action token: %w","messagePattern":"failed to get action token: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/mediafire/util.go","lineNumber":349,"sourceCode":"\treturn resp.Response.Links[0].DirectDownload, nil\n}\n\nfunc (d *Mediafire) calculateSHA256(file *os.File) (string, error) {\n\thasher := sha256.New()\n\tif _, err := file.Seek(0, 0); err != nil {\n\t\treturn \"\", err\n\t}\n\tif _, err := io.Copy(hasher, file); err != nil {\n\t\treturn \"\", err\n\t}\n\treturn hex.EncodeToString(hasher.Sum(nil)), nil\n}\n\nfunc (d *Mediafire) uploadCheck(ctx context.Context, filename string, filesize int64, filehash, folderKey string) (*MediafireCheckResponse, error) {\n\n\tactionToken, err := d.getActionToken(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get action token: %w\", err)\n\t}\n\n\tquery := map[string]string{\n\t\t\"session_token\":   actionToken, /* d.SessionToken */\n\t\t\"filename\":        filename,\n\t\t\"size\":            strconv.FormatInt(filesize, 10),\n\t\t\"hash\":            filehash,\n\t\t\"folder_key\":      folderKey,\n\t\t\"resumable\":       \"yes\",\n\t\t\"response_format\": \"json\",\n\t}\n\n\tvar resp MediafireCheckResponse\n\t_, err = d.postForm(\"/upload/check.php\", query, &resp)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/mediafire/util.go#L331-L367","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nactionToken, err := d.getActionToken(ctx)\nif err != nil {\n    return nil, fmt.Errorf(\"failed to get action token: %w\", err)\n}\n\n// after (caller side: distinguish transient token failure from permanent one)\nif _, err := d.uploadCheck(ctx, name, size, hash, folder); err != nil {\n    if strings.Contains(err.Error(), \"action token\") {\n        d.SessionToken = \"\" // force re-login on next call\n    }\n    return err\n}","handlingStrategy":"retry","validationCode":"if d.SessionToken == \"\" {\n    return errors.New(\"mediafire session not initialized; call Init/login first\")\n}","typeGuard":null,"tryCatchPattern":"// Retry once after forced re-login, then surface the wrapped chain\nif _, err := d.uploadCheck(...); err != nil {\n    var tokErr *erris\n    if strings.Contains(err.Error(), \"action token\") {\n        if rl := d.relogin(); rl == nil {\n            if _, err = d.uploadCheck(...); err == nil { return nil }\n        }\n    }\n    return fmt.Errorf(\"uploadCheck failed: %w\", err)\n}","preventionTips":["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"],"tags":["mediafire","auth-token","upload","go","wrapped-error"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}