router-for-me/CLIProxyAPI · error

failed to read auth file: %w

Error message

failed to read auth file: %w

What it means

Thrown by buildAuthFromFileData when os.ReadFile fails on an auth-file path while no in-memory data was supplied. The management API reads credential JSON files from the auth directory to build coreauth.Auth records, and any OS-level read failure (missing file, permission, interrupted read) surfaces here. The %w wrap preserves the underlying fs error for diagnosis.

Source

Thrown at internal/api/handlers/management/auth_files_crud.go:472

	if h.authManager == nil {
		return nil
	}
	auth, err := h.buildAuthFromFileData(path, data)
	if err != nil {
		return err
	}
	return h.upsertAuthRecord(ctx, auth)
}

func (h *Handler) buildAuthFromFileData(path string, data []byte) (*coreauth.Auth, error) {
	if path == "" {
		return nil, fmt.Errorf("auth path is empty")
	}
	if data == nil {
		var err error
		data, err = os.ReadFile(path)
		if err != nil {
			return nil, fmt.Errorf("failed to read auth file: %w", err)
		}
	}
	metadata := make(map[string]any)
	if err := json.Unmarshal(data, &metadata); err != nil {
		return nil, fmt.Errorf("invalid auth file: %w", err)
	}
	provider, _ := metadata["type"].(string)
	if provider == "" {
		provider = "unknown"
	}
	label := provider
	if email, ok := metadata["email"].(string); ok && email != "" {
		label = email
	}
	lastRefresh, hasLastRefresh := extractLastRefreshTimestamp(metadata)

	authID := h.authIDForPath(path)
	if authID == "" {

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Verify the file exists and is readable: ls -l on the exact path from the error's wrapped cause
  2. Check auth-dir config and confirm the service user owns or can read auths/*.json
  3. Re-trigger the auth-file sync/list after fixing permissions so the record is rebuilt
  4. If the file was intentionally deleted, remove its stale record via the management API so it is not re-scanned

Example fix

# before
chmod 600 auths/qwen.json   # owned by root, server runs as appuser
# after
chown appuser:appuser auths/qwen.json && chmod 600 auths/qwen.json
Defensive patterns

Strategy: validation

Validate before calling

// Before triggering an auth-file scan/import:
if info, err := os.Stat(path); err != nil || info.IsDir() {
    return fmt.Errorf("auth file unavailable: %v", err)
}
if info.Mode().Perm()&0o400 == 0 {
    return errors.New("auth file not readable by this user")
}

Type guard

func isReadableAuthFile(path string) bool {
    info, err := os.Stat(path)
    return err == nil && !info.IsDir() && info.Mode().Perm()&0o400 != 0
}

Try / catch

if auth, err := h.buildAuthFromFileData(path, nil); err != nil {
    if os.IsNotExist(errors.Unwrap(err)) { /* stale record: skip or delete */ }
    log.Warnf("skip auth file %s: %v", path, err)
    continue
}

Prevention

When it happens

Trigger: Calling a management endpoint that imports or lists auth files (paths where data==nil is passed) when the given path has been deleted, renamed, or has mode 0600 owned by another user between listing and reading; a path outside the auth dir that does not exist.

Common situations: Auth files manually removed or rotated while the server runs; auth-dir misconfiguration pointing to a nonexistent directory; running the service as a different user than the owner of auths/*.json; a stale path cached from a previous config.

Related errors


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