router-for-me/CLIProxyAPI · error
pluginhost: command-line auth %d is invalid
Error message
pluginhost: command-line auth %d is invalid
What it means
While persisting auths returned by a plugin command-line run, each pluginapi.AuthData is converted with AuthDataToCoreAuth; a nil result means that auth entry (1-based index in the message) is invalid — missing provider, unusable type, or empty value payload — and the whole persistence batch aborts, returning the paths saved so far plus this error.
Source
Thrown at internal/pluginhost/command_line.go:383
func (h *Host) persistCommandLineAuths(ctx context.Context, auths []pluginapi.AuthData) ([]string, error) {
if len(auths) == 0 {
return nil, nil
}
store := sdkAuth.GetTokenStore()
if store == nil {
return nil, fmt.Errorf("pluginhost: token store unavailable")
}
summary := h.hostConfigSummary()
if summary.AuthDir != "" {
if setter, okSetter := store.(interface{ SetBaseDir(string) }); okSetter {
setter.SetBaseDir(summary.AuthDir)
}
}
savedPaths := make([]string, 0, len(auths))
for index, authData := range auths {
record := h.AuthDataToCoreAuth(authData, "", "")
if record == nil {
return savedPaths, fmt.Errorf("pluginhost: command-line auth %d is invalid", index+1)
}
savedPath, errSave := store.Save(ctx, record)
if errSave != nil {
return savedPaths, fmt.Errorf("pluginhost: save command-line auth %s: %w", record.ID, errSave)
}
if strings.TrimSpace(savedPath) != "" {
savedPaths = append(savedPaths, savedPath)
}
}
return savedPaths, nil
}
func appendCommandLineSavedPaths(stdout []byte, savedPaths []string) []byte {
if len(savedPaths) == 0 {
return stdout
}
out := append([]byte(nil), stdout...)
if len(out) > 0 && out[len(out)-1] != '\n' {View on GitHub (pinned to 78f0c4079e)
Solutions
- Identify which entry failed from the 1-based index in the message and dump the plugin's returned AuthData list for inspection.
- Fix the plugin to omit invalid entries or fail the command with a proper error rather than returning partial auth data.
- Check auths already persisted before the failing index — remove duplicates if you re-run the command after fixing.
- Align plugin and host on the same pluginapi version.
Example fix
// plugin side, before
return pluginapi.CommandLineResponse{
Auths: []pluginapi.AuthData{{Provider: "myprov"}, validAuth}, // first entry lacks values
}, nil
// after
auths := []pluginapi.AuthData{}
if validAuth.Provider != "" {
auths = append(auths, validAuth)
}
return pluginapi.CommandLineResponse{Auths: auths}, nil Defensive patterns
Strategy: validation
Validate before calling
// Filter plugin-returned auths before persistence
for i, a := range auths {
if strings.TrimSpace(a.Provider) == "" || len(a.StorageJSON) == 0 {
return fmt.Errorf("plugin returned invalid auth at index %d", i+1)
}
} Type guard
func allAuthDataValid(auths []pluginapi.AuthData) bool {
for _, a := range auths {
if strings.TrimSpace(a.Provider) == "" {
return false
}
}
return true
} Try / catch
paths, err := host.PersistCommandLineAuths(ctx, auths)
if err != nil {
if strings.Contains(err.Error(), "auth %d is invalid") {
// partial success: paths contains entries already saved; dedupe before re-run
return cleanupPartial(paths, err)
}
return err
} Prevention
- Plugins should validate their own AuthData before returning it.
- After a partial-save failure, reconcile saved paths against the store to avoid duplicates.
When it happens
Trigger: A plugin's command-line response includes an AuthData entry with an empty provider ID, unsupported auth type, or no credential value. Any earlier valid entries are already saved (partial success) when the error returns.
Common situations: Plugin emits placeholder/empty auth entries when login fails midway instead of returning an error; schema drift between plugin and pluginapi versions; plugin returns multiple auths where one is incompletely populated.
Related errors
- auth provider %s returned auth without provider
- auth provider %s returned invalid auth data
- auth provider refresh returned invalid auth data
- auth_index is required
- invalid auth file name
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/13a804f5ba1e5d9b.
Report an issue: GitHub.