router-for-me/CLIProxyAPI · error

auth provider refresh returned invalid auth data

Error message

auth provider refresh returned invalid auth data

What it means

After a plugin's RefreshAuth returns new auth data, the host merges it with the existing auth (filling missing fields from the old record) and converts it to a core auth object via AuthDataToCoreAuth. If that conversion yields nil, the merged pluginapi.AuthData is fundamentally invalid (no usable provider/type/value combination) and this error is returned with handled=true.

Source

Thrown at internal/pluginhost/auth_provider.go:398

		data.ProxyURL = auth.ProxyURL
	}
	if len(data.Metadata) == 0 {
		data.Metadata = cloneAnyMap(auth.Metadata)
	}
	if len(data.Attributes) == 0 {
		data.Attributes = cloneStringMap(auth.Attributes)
	}
	if len(data.StorageJSON) == 0 {
		data.StorageJSON = storageJSONFromAuth(auth)
	}
	if pluginResp.NextRefreshAfter.IsZero() {
		data.NextRefreshAfter = auth.NextRefreshAfter
	} else {
		data.NextRefreshAfter = pluginResp.NextRefreshAfter
	}
	next := h.AuthDataToCoreAuth(data, "", data.FileName)
	if next == nil {
		return nil, true, fmt.Errorf("auth provider refresh returned invalid auth data")
	}
	next.Index = auth.Index
	next.CreatedAt = auth.CreatedAt
	next.UpdatedAt = auth.UpdatedAt
	return next, true, nil
}

func (h *Host) AuthDataToCoreAuth(data pluginapi.AuthData, path, fileName string) *coreauth.Auth {
	authDir := ""
	if h != nil {
		authDir = h.hostConfigSummary().AuthDir
	}
	return pluginAuthDataToCoreAuth(data, path, fileName, authDir)
}

type pluginTokenStorage struct {
	provider string
	rawJSON  []byte

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Log or inspect the plugin's AuthRefreshResponse: check that Provider, Type/URL fields, and value payload are all populated.
  2. Fix the plugin so RefreshAuth echoes back the AuthData it received (with updated token values) rather than a partial struct.
  3. If the plugin means 'no refresh needed', return the original storage unchanged or an explicit no-op signal, never an empty AuthData.
  4. Update the pluginhost/plugin pair together so both use the same pluginapi version.

Example fix

// plugin side, before
return pluginapi.AuthRefreshResponse{
	NextRefreshAfter: time.Now().Add(time.Hour), // everything else empty -> host cannot build core auth
}, nil

// after
out := req.AsAuthData() // echo received data
out.AccessToken = newToken
out.NextRefreshAfter = time.Now().Add(time.Hour)
return pluginapi.AuthRefreshResponse{AuthData: out}, nil
Defensive patterns

Strategy: validation

Validate before calling

// Plugin-side, before returning from RefreshAuth
func validAuthData(d pluginapi.AuthData) bool {
    return strings.TrimSpace(d.Provider) != "" && len(d.StorageJSON) > 0
}
if !validAuthData(out) {
    return pluginapi.AuthRefreshResponse{}, fmt.Errorf("refresh produced incomplete auth data")
}

Type guard

func (d pluginapi.AuthData) IsValid() bool {
    return strings.TrimSpace(d.Provider) != "" && (len(d.StorageJSON) > 0 || len(d.Attributes) > 0)
}

Try / catch

next, handled, err := host.CallRefreshAuth(ctx, auth)
if err != nil && strings.Contains(err.Error(), "invalid auth data") {
    // plugin returned a partial refresh payload; force re-login for this provider
    return forceReLogin(auth)
}

Prevention

When it happens

Trigger: A plugin's RefreshAuth response that omits required fields: empty provider identifier, unknown auth type, or a value payload the host cannot map to a core auth record. The merge only backfills Attributes, StorageJSON, and NextRefreshAfter — it cannot fix a missing provider or type.

Common situations: Plugin returns a refresh response with only NextRefreshAfter set (host backfills StorageJSON but the type/provider fields stay empty); plugin written against an older AuthData schema; plugin intentionally returns an empty response to signal 'nothing changed' instead of using the agreed mechanism.

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/56982f24f7aa1c8c. Report an issue: GitHub.