router-for-me/CLIProxyAPI · error
failed to update auth %s: %w
Error message
failed to update auth %s: %w
What it means
After the source file's disabled flag was persisted, propagating the state to every runtime auth expanded from that source failed at authManager.Update for the auth named by %s. The file on disk and the in-memory registry can now be out of sync — the file says disabled but that one runtime auth record could not be updated.
Source
Thrown at internal/api/handlers/management/auth_files_fields.go:148
if errWrite := setSourceAuthFileDisabled(sourcePath, disabled); errWrite != nil {
if os.IsNotExist(errWrite) {
return errAuthFileNotFound
}
return fmt.Errorf("failed to update source auth file: %w", errWrite)
}
now := time.Now()
for _, auth := range h.authManager.List() {
if auth == nil {
continue
}
if !sameAuthFilePath(authAttribute(auth, "path"), sourcePath) &&
!sameAuthFilePath(authAttribute(auth, coreauth.AttributeVirtualSource), sourcePath) {
continue
}
applyAuthDisabledState(auth, disabled)
auth.UpdatedAt = now
if _, errUpdate := h.authManager.Update(ctx, auth); errUpdate != nil {
return fmt.Errorf("failed to update auth %s: %w", auth.ID, errUpdate)
}
}
return nil
}
func setSourceAuthFileDisabled(path string, disabled bool) error {
path = strings.TrimSpace(path)
if path == "" {
return fmt.Errorf("source auth path is empty")
}
data, errRead := os.ReadFile(path)
if errRead != nil {
return errRead
}
metadata := make(map[string]any)
if len(bytes.TrimSpace(data)) > 0 {
if errUnmarshal := json.Unmarshal(data, &metadata); errUnmarshal != nil {
return fmt.Errorf("invalid auth file: %w", errUnmarshal)View on GitHub (pinned to 78f0c4079e)
Solutions
- Retry the toggle request — re-running re-reads the file and re-applies state to all children idempotently
- If using a remote store, check its connectivity/health and retry after it recovers
- Avoid concurrent toggle and rotate/delete operations on the same source; sequence them
- Verify final state via GET on the auth list and manually toggle again if any child drifted
Example fix
# before: concurrent curl -X PATCH .../disable & curl -X POST .../rotate & # after: sequential curl -X POST .../rotate && curl -X PATCH .../disable
Defensive patterns
Strategy: retry
Try / catch
err := patchPluginVirtualSourceStatus(ctx, auth, disabled)
if err != nil && strings.Contains(err.Error(), "failed to update auth") {
// source file persisted; a retry reconciles runtime children idempotently
auth = refreshAuthFromManager(auth)
err = patchPluginVirtualSourceStatus(ctx, auth, disabled)
} Prevention
- Do not run rotate/delete concurrently with enable-disable on the same source
- Keep remote stores (PG/git) healthy before batch toggles
- Verify final state with a list GET after toggling
When it happens
Trigger: PATCH toggle on a plugin virtual source where one of its expanded child auths is concurrently deleted or rotated out between List() and Update(); a store-level failure (Postgres connection drop when using PGSTORE_*, file lock contention on the file store).
Common situations: Two admins toggling/rotating credentials simultaneously; background token refresh re-writing the auth concurrently; external store (PG/git/object store) briefly unavailable mid-operation.
Related errors
- post-auth persist hook failed: %w
- failed to read auth file: %w
- invalid auth file: %w
- core auth manager unavailable
- failed to update source auth file: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/478ccfa9683e2318.
Report an issue: GitHub.