router-for-me/CLIProxyAPI · critical

auth directory is unavailable

Error message

auth directory is unavailable

What it means

listAuthFilesFromDisk needs the auth directory but h.resolvedAuthDir() returned an empty string — the host has no usable auth directory configured/resolvable, so listing auth files from disk is impossible. This is a host configuration problem, not a plugin problem.

Source

Thrown at internal/pluginhost/auth_callbacks.go:156

		auths := manager.List()
		entries := make([]pluginapi.HostAuthFileEntry, 0, len(auths))
		for _, auth := range auths {
			if entry := h.buildHostAuthFileEntry(auth); entry != nil {
				entries = append(entries, *entry)
			}
		}
		sort.Slice(entries, func(i, j int) bool {
			return strings.ToLower(entries[i].Name) < strings.ToLower(entries[j].Name)
		})
		return entries, nil
	}
	return h.listAuthFilesFromDisk()
}

func (h *Host) listAuthFilesFromDisk() ([]pluginapi.HostAuthFileEntry, error) {
	authDir := h.resolvedAuthDir()
	if authDir == "" {
		return nil, fmt.Errorf("auth directory is unavailable")
	}
	entries, errReadDir := os.ReadDir(authDir)
	if errReadDir != nil {
		return nil, fmt.Errorf("failed to read auth dir: %w", errReadDir)
	}
	files := make([]pluginapi.HostAuthFileEntry, 0)
	for _, entry := range entries {
		if entry.IsDir() {
			continue
		}
		name := entry.Name()
		if !strings.HasSuffix(strings.ToLower(name), ".json") {
			continue
		}
		full := filepath.Join(authDir, name)
		fileEntry := pluginapi.HostAuthFileEntry{
			Name:   name,
			Source: "file",

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Set a concrete auth directory in config (the auths/ default, or your custom path) and confirm it exists on disk
  2. Verify the server actually loaded the intended config file (--config path) and check startup logs for auth-dir resolution
  3. If using an external secret store, ensure a local auth dir is still configured for plugin auth file access, or migrate plugin auth to the supported path
  4. Restart the host after fixing config so resolvedAuthDir picks up the value

Example fix

# config.yaml — before
auth-dir: ""

# config.yaml — after
auth-dir: "./auths"
Defensive patterns

Strategy: fallback

Validate before calling

// Startup check before enabling plugins:
if dir := host.ResolvedAuthDir(); dir == "" {
    return errors.New("auth directory not configured; set auth-dir in config.yaml")
}
if info, err := os.Stat(dir); err != nil || !info.IsDir() {
    return fmt.Errorf("auth dir %s missing or not a directory", dir)
}

Prevention

When it happens

Trigger: The auth-manager path is unavailable (manager not initialized) and the configured/fallback auth dir resolves to empty — e.g. auth-dir config empty, config not loaded, or the host started in a mode where auth storage is not file-based and no dir was resolved.

Common situations: Config yaml missing or with an empty auths/auth-dir setting; running the host with a config that relies on an external store (Postgres/git/object) without a local auth dir; working directory changed so relative auth dir resolution fails at startup.

Related errors


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