AlistGo/alist · critical

failed to refresh token: %s

Error message

failed to refresh token: %s

What it means

Thrown when the Dropbox OAuth token endpoint (POST with grant_type=refresh_token) answers with a non-200 status. The response body is included in the message and typically contains error and error_description fields such as invalid_grant or invalid_client. This is a hard authentication configuration failure, not a transient error.

Source

Thrown at drivers/dropbox/util.go:38

		url = d.OauthTokenURL
	}
	var tokenResp TokenResp
	resp, err := base.RestyClient.R().
		//ForceContentType("application/x-www-form-urlencoded").
		//SetBasicAuth(d.ClientID, d.ClientSecret).
		SetFormData(map[string]string{
			"grant_type":    "refresh_token",
			"refresh_token": d.RefreshToken,
			"client_id":     d.ClientID,
			"client_secret": d.ClientSecret,
		}).
		Post(url)
	if err != nil {
		return err
	}
	log.Debugf("[dropbox] refresh token response: %s", resp.String())
	if resp.StatusCode() != 200 {
		return fmt.Errorf("failed to refresh token: %s", resp.String())
	}
	_ = utils.Json.UnmarshalFromString(resp.String(), &tokenResp)
	d.AccessToken = tokenResp.AccessToken
	op.MustSaveDriverStorage(d)
	return nil
}

func (d *Dropbox) request(uri, method string, callback base.ReqCallback, retry ...bool) ([]byte, error) {
	req := base.RestyClient.R()
	req.SetHeader("Authorization", "Bearer "+d.AccessToken)
	if d.RootNamespaceId != "" {
		apiPathRootJson, err := utils.Json.MarshalToString(map[string]interface{}{
			".tag": "root",
			"root": d.RootNamespaceId,
		})
		if err != nil {
			return nil, err
		}

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Read the response body in the message: invalid_grant means generate a NEW refresh token via the OAuth flow; invalid_client means fix ClientID/ClientSecret
  2. Confirm ClientID and ClientSecret come from the same Dropbox app page that produced the refresh token
  3. If the app was recreated, repeat the full authorization flow and update all three fields
  4. After fixing, restart/reload the driver so Init re-runs cleanly
Defensive patterns

Strategy: try-catch

Try / catch

// refreshToken
if err := d.refreshToken(); err != nil {
    if strings.Contains(err.Error(), "failed to refresh token") {
        // fatal config error: stop retrying and flag storage as needing re-auth
        log.Errorf("dropbox refresh token rejected: %s", err)
        return err
    }
    return err // transient network error: safe to retry later
}

Prevention

When it happens

Trigger: Expired, revoked, or single-use refresh token (invalid_grant); mismatched client_id/client_secret (invalid_client); the refresh token was issued for a different Dropbox app than the one configured; Dropbox app is disabled.

Common situations: Reusing a refresh token after regenerating the app secret; copying the app key into the secret field; rotating tokens in another tool which invalidated the old one; token issued in production mode used against a development-mode app for an uninvited user.

Related errors


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