router-for-me/CLIProxyAPI · error

plugin executor %s refresh returned invalid auth data

Error message

plugin executor %s refresh returned invalid auth data

What it means

The plugin's RefreshAuth returned data, the host normalized it via AuthDataToCoreAuth, and the result was nil — meaning the plugin's refreshed auth payload is structurally invalid (e.g. missing file name/type, unparseable storage JSON, or empty required identity fields), so no usable core Auth could be constructed.

Source

Thrown at internal/pluginhost/adapters_executors.go:752

	}
	if len(data.Metadata) == 0 && auth != nil {
		data.Metadata = cloneAnyMap(auth.Metadata)
	}
	if len(data.Attributes) == 0 && auth != nil {
		data.Attributes = cloneStringMap(auth.Attributes)
	}
	if len(data.StorageJSON) == 0 {
		data.StorageJSON = storageJSONFromAuth(auth)
	}
	if pluginResp.NextRefreshAfter.IsZero() && auth != nil {
		data.NextRefreshAfter = auth.NextRefreshAfter
	}
	if !pluginResp.NextRefreshAfter.IsZero() {
		data.NextRefreshAfter = pluginResp.NextRefreshAfter
	}
	next := a.host.AuthDataToCoreAuth(data, "", data.FileName)
	if next == nil {
		return nil, fmt.Errorf("plugin executor %s refresh returned invalid auth data", a.Identifier())
	}
	if auth != nil {
		next.CreatedAt = auth.CreatedAt
		next.UpdatedAt = auth.UpdatedAt
	}
	return next, nil
}

func (a *executorAdapter) CountTokens(ctx context.Context, auth *coreauth.Auth, req coreexecutor.Request, opts coreexecutor.Options) (resp coreexecutor.Response, err error) {
	if a == nil || a.executor == nil || a.host.isPluginFused(a.pluginID) || !a.host.pluginIdentityCurrent(a.pluginID, a.path, a.version) {
		return coreexecutor.Response{}, fmt.Errorf("plugin executor %s is unavailable", a.Identifier())
	}
	defer func() {
		if recovered := recover(); recovered != nil {
			a.host.fusePlugin(a.pluginID, "Executor.CountTokens", recovered)
			resp = coreexecutor.Response{}
			err = fmt.Errorf("plugin executor %s count tokens panic: %v", a.Identifier(), recovered)
		}

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Log/inspect the plugin's raw RefreshAuth response payload (data) to see which required fields are empty or malformed
  2. Fix the plugin to return complete refresh data: valid StorageJSON, FileName, provider and ID consistent with the auth being refreshed
  3. Align the plugin with the host's plugin API version (check AuthDataToCoreAuth requirements) and rebuild
  4. If the plugin cannot be fixed quickly, bypass plugin refresh by re-authenticating the provider natively
Defensive patterns

Strategy: validation

Validate before calling

// Before accepting the plugin build, verify its refresh output round-trips:
func validRefreshPayload(p pluginapi.AuthRefreshResponse) error {
    if p.StorageJSON == nil || len(p.StorageJSON) == 0 { return errors.New("empty StorageJSON") }
    if strings.TrimSpace(p.FileName) == "" { return errors.New("empty FileName") }
    var probe map[string]any
    return json.Unmarshal(p.StorageJSON, &probe)
}

Prevention

When it happens

Trigger: A plugin RefreshAuth response whose StorageJSON/FileName/attributes are empty or malformed such that AuthDataToCoreAuth returns nil; note the code backfills empty StorageJSON and NextRefreshAfter from the old auth first, so nil usually means the plugin-supplied fields themselves are invalid.

Common situations: Plugin returns an empty or partially-filled refresh response; plugin writes a different auth schema than the host's AuthDataToCoreAuth expects; plugin API version mismatch between plugin and host.

Related errors


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