router-for-me/CLIProxyAPI · error

failed to create token file: %w

Error message

failed to create token file: %w

What it means

os.Create on the auth file path failed after the directory was successfully created. The token is not persisted, so a successful OAuth login is lost on restart. The wrapped error distinguishes permission issues from path problems (name too long, is-a-directory, O_RDONLY filesystem).

Source

Thrown at internal/auth/claude/token.go:91

func (ts *ClaudeTokenStorage) SaveTokenToFile(authFilePath string) error {
	misc.LogSavingCredentials(authFilePath)
	ts.Type = "claude"

	// Create directory structure if it doesn't exist
	if err := os.MkdirAll(filepath.Dir(authFilePath), 0700); err != nil {
		return fmt.Errorf("failed to create directory: %v", err)
	}

	// Merge metadata using helper
	data, errMerge := misc.MergeMetadata(ts, ts.Metadata)
	if errMerge != nil {
		return fmt.Errorf("failed to merge metadata: %w", errMerge)
	}

	// Create the token file
	f, err := os.Create(authFilePath)
	if err != nil {
		return fmt.Errorf("failed to create token file: %w", err)
	}
	defer func() {
		if errClose := f.Close(); errClose != nil {
			log.Errorf("claude token storage: close token file error: %v", errClose)
		}
	}()

	// Encode and write the token data as JSON
	if err = json.NewEncoder(f).Encode(data); err != nil {
		return fmt.Errorf("failed to write token to file: %w", err)
	}
	return nil
}

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Check the wrapped error text and fix the specific cause: chmod the directory (needs w+x for the runtime user) or remove the conflicting directory at the file path.
  2. Confirm the auth-dir volume is mounted read-write in containers.
  3. Verify the full resolved path is a file location, not a directory.

Example fix

# before
chmod 111 auths   # traverse-only: mkdir check passes, file create fails

# after
chmod 700 auths && chown appuser auths
Defensive patterns

Strategy: validation

Validate before calling

if info, err := os.Stat(authFilePath); err == nil && info.IsDir() {
    return errors.New("auth file path is a directory")
}
f, err := os.OpenFile(authFilePath, os.O_WRONLY|os.O_CREATE, 0600)
if err != nil { return fmt.Errorf("cannot write auth file: %w", err) }
f.Close()

Try / catch

if err := storage.SaveTokenToFile(path); err != nil && strings.Contains(err.Error(), "failed to create token file") {
    log.Errorf("check permissions on %s", filepath.Dir(path))
}

Prevention

When it happens

Trigger: The directory exists and is writable enough for MkdirAll to succeed, but creating the file itself fails: directory without write permission for the file (execute-only traversal), the target path is itself a directory, read-only mount, or filename constraints exceeded.

Common situations: auth-dir with mode that allows mkdir traversal but not file creation; auth file path accidentally set to an existing directory; read-only container filesystems where MkdirAll no-ops on existing dirs but Create fails; path length limits with deeply nested auth-dirs.

Related errors


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