router-for-me/CLIProxyAPI · error
failed to read auth file: %w
Error message
failed to read auth file: %w
What it means
Wrapped I/O error from os.ReadFile in Host.authPhysicalJSONByIndex when reading the auth file fails for a reason other than not-existing (permissions, I/O error, path issues). The %w wrap preserves the underlying filesystem error for diagnosis.
Source
Thrown at internal/pluginhost/auth_callbacks.go:250
}
return nil, fmt.Errorf("auth not found for auth_index %s", authIndex)
}
func (h *Host) authPhysicalJSONByIndex(authIndex string) (*coreauth.Auth, []byte, error) {
auth, errGet := h.authByIndex(authIndex)
if errGet != nil {
return nil, nil, errGet
}
path := strings.TrimSpace(authAttribute(auth, "path"))
if path == "" {
return nil, nil, fmt.Errorf("auth file path not found for auth_index %s", authIndex)
}
data, errRead := os.ReadFile(path)
if errRead != nil {
if os.IsNotExist(errRead) {
return nil, nil, fmt.Errorf("auth file not found for auth_index %s", authIndex)
}
return nil, nil, fmt.Errorf("failed to read auth file: %w", errRead)
}
if len(bytesTrimSpace(data)) == 0 {
return nil, nil, fmt.Errorf("auth file is empty for auth_index %s", authIndex)
}
var metadata map[string]any
if errUnmarshal := json.Unmarshal(data, &metadata); errUnmarshal != nil {
return nil, nil, fmt.Errorf("invalid auth file for auth_index %s: %w", authIndex, errUnmarshal)
}
return auth, data, nil
}
func validateHostAuthSaveRequest(req pluginapi.HostAuthSaveRequest) (string, []byte, error) {
name := strings.TrimSpace(req.Name)
if isUnsafeAuthFileName(name) {
return "", nil, fmt.Errorf("invalid auth file name")
}
if !strings.HasSuffix(strings.ToLower(name), ".json") {
return "", nil, fmt.Errorf("auth file name must end with .json")View on GitHub (pinned to 78f0c4079e)
Solutions
- Inspect the wrapped error (errors.Unwrap / errors.As to *fs.PathError) for the real cause
- Fix ownership/permissions: the process user must read auths/<file>.json (chmod 600 with correct owner)
- If it is a transient rename race, retry the read once after a short delay
Defensive patterns
Strategy: try-catch
Try / catch
var pathErr *fs.PathError
if errors.As(err, &pathErr) {
switch {
case errors.Is(pathErr.Err, fs.ErrPermission):
// fix ownership/mode on the auth dir
default:
// log wrapped errno and retry once for transient I/O
}
} Prevention
- Run the process as the user that owns auths/ with mode 600 files, 700 dir
- Use atomic write-then-rename producers so readers never see half-states
When it happens
Trigger: Auth file present but mode 0000 or owned by another user; reading during concurrent atomic replace (rename-on-write) hitting a transient moment; disk or NFS-level I/O failure; directory in place of the expected file.
Common situations: Running the proxy as a different user than the one that created auths/; files copied with restrictive umask; network-backed auth directory with intermittent I/O errors.
Related errors
- failed to write auth file: %w
- auth file path not found for auth_index %s
- auth file not found for auth_index %s
- auth file is empty for auth_index %s
- pluginhost: save command-line auth %s: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/94797b3468c0a669.
Report an issue: GitHub.