{"record":{"id":"1a4cf7f516b8f5ee","repo":"AlistGo/alist","slug":"failed-to-renew-token-w","errorCode":null,"errorMessage":"failed to renew token: %w","messagePattern":"failed to renew token: %w","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/mediafire/util.go","lineNumber":126,"sourceCode":"\td.SessionToken = tokenResp.Response.SessionToken\n\n\t//fmt.Printf(\"Init :: Obtain Session Token %v\", d.SessionToken)\n\n\top.MustSaveDriverStorage(d)\n\n\treturn d.SessionToken, nil\n}\n\nfunc (d *Mediafire) renewToken(_ context.Context) error {\n\tquery := map[string]string{\n\t\t\"session_token\":   d.SessionToken,\n\t\t\"response_format\": \"json\",\n\t}\n\n\tvar resp MediafireRenewTokenResponse\n\t_, err := d.postForm(\"/user/renew_session_token.php\", query, &resp)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to renew token: %w\", err)\n\t}\n\n\t//fmt.Printf(\"getInfo :: Raw response: %s\\n\", string(body))\n\t//fmt.Printf(\"getInfo :: Parsed response: %+v\\n\", resp)\n\n\tif resp.Response.Result != \"Success\" {\n\t\treturn fmt.Errorf(\"MediaFire token renewal failed: %s\", resp.Response.Result)\n\t}\n\n\td.SessionToken = resp.Response.SessionToken\n\n\t//fmt.Printf(\"Init :: Renew Session Token: %s\", resp.Response.Result)\n\n\top.MustSaveDriverStorage(d)\n\n\treturn nil\n}\n","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/mediafire/util.go#L108-L144","documentation":"renewToken wraps a transport-level failure from postForm against /user/renew_session_token.php: network unreachable, timeout, DNS failure, TLS error, or the response body failing to unmarshal into MediafireRenewTokenResponse (API format change, HTML error page). The %w preserves the underlying cause. This is the cron-job path (Init schedules renewal every 6-9 minutes), so failures here surface as an expired-token cascade in later API calls.","triggerScenarios":"The renewal cron firing during a network blip or MediaFire outage; MediaFire returning an HTML Cloudflare challenge page that fails JSON unmarshal; proxy misconfiguration on the host.","commonSituations":"Servers with flaky egress; token renewal errors silently ignored (cron Do discards the error) until the session actually expires and every driver call fails.","solutions":["Inspect the wrapped error: net/DNS/timeout issues are environmental; JSON errors suggest an HTML or changed response","Make renewal errors observable (log them) instead of discarding in the cron callback","On next failure, fall back to a full getSessionToken with a fresh cookie rather than endless renew attempts","Retry with backoff for transient network failures"],"exampleFix":"// before: cron discards the renewal error\nd.cron.Do(func() {\n    d.renewToken(ctx)\n})\n\n// after: log and escalate to full token re-acquisition\nd.cron.Do(func() {\n    if err := d.renewToken(ctx); err != nil {\n        log.Printf(\"[mediafire] token renewal failed: %v, re-authenticating\", err)\n        if err2 := d.getSessionToken(ctx); err2 != nil {\n            log.Printf(\"[mediafire] re-auth failed: %v\", err2)\n        }\n    }\n})","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"In the cron callback, check the error: for net.Error/timeout, retry with backoff (up to 3 attempts); for JSON unmarshal failures, capture and log the body; if renewal keeps failing, fall back to full getSessionToken with a fresh cookie.","preventionTips":["Never discard cron errors — log every renewal failure","Chain renewToken failure into getSessionToken escalation","Keep the wrapped %w intact so the root cause stays visible in logs"],"tags":["mediafire","network","token-renewal","cron","error-wrapping"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}