{"record":{"id":"ac98952f275c7462","repo":"router-for-me/CLIProxyAPI","slug":"failed-to-write-token-to-file-w-ac9895","errorCode":null,"errorMessage":"failed to write token to file: %w","messagePattern":"failed to write token to file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/auth/codex/token.go","lineNumber":81,"sourceCode":"\n\t// Merge metadata using helper\n\tdata, errMerge := misc.MergeMetadata(ts, ts.Metadata)\n\tif errMerge != nil {\n\t\treturn fmt.Errorf(\"failed to merge metadata: %w\", errMerge)\n\t}\n\n\tf, err := os.Create(authFilePath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create token file: %w\", err)\n\t}\n\tdefer func() {\n\t\tif errClose := f.Close(); errClose != nil {\n\t\t\tlog.Errorf(\"codex token storage: close token file error: %v\", errClose)\n\t\t}\n\t}()\n\n\tif err = json.NewEncoder(f).Encode(data); err != nil {\n\t\treturn fmt.Errorf(\"failed to write token to file: %w\", err)\n\t}\n\treturn nil\n}\n","sourceCodeStart":63,"sourceCodeEnd":85,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/auth/codex/token.go#L63-L85","documentation":"json.NewEncoder(f).Encode(data) failed writing the serialized token to the opened file — an I/O error during the actual write or flush, not during open. Common causes: disk full (ENOSPC), quota exceeded, or the filesystem being remounted read-only after open. Because the encoder streams directly to the file, a mid-write failure can leave a truncated (invalid) JSON file behind.","triggerScenarios":"Disk full at the moment of saving credentials; per-user quota hit on the volume; file opened then the underlying device/vanished (ejected volume, dead NFS server); fcntl locks not a factor but VM disk limits are.","commonSituations":"Small container filesystems filling up with logs; long-running servers whose volume hits quota right when a refreshed token is persisted; network storage blipping mid-write.","solutions":["Check space: `df -h <auth-dir>` and inodes with `df -i <auth-dir>`; free space if full.","After fixing, verify the auth file is valid JSON (a truncated write leaves a corrupt file) and re-login/refresh if not.","Raise disk quota / enlarge the container volume.","Alert on disk usage for the volume hosting auths/ so credential saves never hit ENOSPC.","Consider a storage backend (Postgres/object store) where writes are transactional if local-disk truncation is a recurring risk."],"exampleFix":"# before: auths on a full rootfs\ndf -h /  # 100%\n# after: free space or move auth-dir to a healthy volume\ncli-proxy-api --config config.yaml   # with auth-dir: /data/auths","handlingStrategy":"validation","validationCode":"// Check writable space before persisting credentials\nvar stat syscall.Statfs_t\nif err := syscall.Statfs(filepath.Dir(path), &stat); err == nil {\n    free := stat.Bavail * uint64(stat.Bsize)\n    if free < 1<<20 { // < 1 MiB\n        return errors.New(\"auth volume nearly full; token save would be truncated\")\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := ts.SaveTokenToFile(path); err != nil {\n    if strings.Contains(err.Error(), \"failed to write token to file\") {\n        // ENOSPC/quota: free space, then re-save; verify file is valid JSON afterwards\n    }\n}","preventionTips":["Monitor disk space on the volume hosting auths/.","After any failed save, validate the auth file with json.Valid before reusing it.","Keep credentials on a volume with headroom or use a database/object-store backend."],"tags":["filesystem","disk-full","storage","codex","io"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}