router-for-me/CLIProxyAPI · error
failed to create token file: %w
Error message
failed to create token file: %w
What it means
Returned by KimiTokenStorage.SaveTokenToFile when os.Create fails on the target auth file path (token.go:98-100). The directory was created successfully just before, so the failure is specific to the file itself: permission denied on the directory, path is a directory, name too long, or disk full.
Source
Thrown at internal/auth/kimi/token.go:99
// SaveTokenToFile serializes the Kimi token storage to a JSON file.
func (ts *KimiTokenStorage) SaveTokenToFile(authFilePath string) error {
misc.LogSavingCredentials(authFilePath)
ts.Type = "kimi"
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)
}
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("kimi token storage: close token file error: %v", errClose)
}
}()
encoder := json.NewEncoder(f)
encoder.SetIndent("", " ")
if err = encoder.Encode(data); err != nil {
return fmt.Errorf("failed to write token to file: %w", err)
}
return nil
}
// IsExpired checks if the token has expired.
func (ts *KimiTokenStorage) IsExpired() bool {
if ts.Expired == "" {View on GitHub (pinned to 78f0c4079e)
Solutions
- Verify the path is a regular file location, not an existing directory: ls -la auths/
- Grant write permission on the directory to the running user: chown -R appuser: auths/ && chmod 700 auths/
- Check disk space and inodes: df -h && df -i
- On SELinux systems, check the audit log and fix the context of the auths directory
Example fix
# before ls -la auths/ # shows kimi-token.json is a DIRECTORY # after rm -rf auths/kimi-token.json # remove the directory so os.Create can make a file
Defensive patterns
Strategy: validation
Validate before calling
if info, err := os.Stat(authFilePath); err == nil && info.IsDir() {
return fmt.Errorf("auth file path %q is a directory", authFilePath)
} Try / catch
if err := ts.SaveTokenToFile(path); err != nil {
if strings.Contains(err.Error(), "failed to create token file") {
log.Errorf("cannot write %s: check perms/disk", path)
}
return err
} Prevention
- Ensure no directories share names with intended token files under auths/
- Run the process as the owner of the auths directory
- Verify with touch auths/.write-test at startup
When it happens
Trigger: authFilePath points at an existing directory; the parent directory exists but lacks write permission for the process user; filesystem out of space or inodes; the file already exists as an immutable/locked file.
Common situations: auths/ owned by root while the proxy runs unprivileged; a leftover directory named like the target token file (e.g. auths/kimi-xxx.json/); full disk in a container; SELinux denying creation.
Related errors
- failed to create directory: %v
- failed to update source auth file: %w
- failed to create directory: %v
- failed to write token to file: %w
- vertex credential: create directory failed: %w
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/d6ade0f143cba50b.
Report an issue: GitHub.