{"record":{"id":"8daec6226202f281","repo":"router-for-me/CLIProxyAPI","slug":"failed-to-create-token-file-w-8daec6","errorCode":null,"errorMessage":"failed to create token file: %w","messagePattern":"failed to create token file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/auth/codex/token.go","lineNumber":72,"sourceCode":"//\n// Returns:\n//   - error: An error if the operation fails, nil otherwise\nfunc (ts *CodexTokenStorage) SaveTokenToFile(authFilePath string) error {\n\tmisc.LogSavingCredentials(authFilePath)\n\tts.Type = \"codex\"\n\tif err := os.MkdirAll(filepath.Dir(authFilePath), 0700); err != nil {\n\t\treturn fmt.Errorf(\"failed to create directory: %v\", err)\n\t}\n\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":54,"sourceCodeEnd":85,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/auth/codex/token.go#L54-L85","documentation":"os.Create failed opening the auth file for writing after the directory was created successfully. Causes: permission denied inside an existing directory, the target path is itself a directory, a read-only filesystem, or OS-level open-file limits. Note os.Create truncates an existing file, so a locked file can also surface here on some platforms.","triggerScenarios":"auths directory writable-check passed at mkdir time but file creation denied (sticky bit, ACL); the configured auth file path points at an existing directory; disk mounted read-only between mkdir and create; SELinux denying file creation in the context.","commonSituations":"SELinux/AppArmor denials on containers; path configuration ending in a trailing slash making the target a directory; NFS volume with root_squash denying the app user.","solutions":["Manually test creation: `touch <auth-file-path>` as the same user — the OS error will name the real cause.","Fix ownership/ACLs on the auth directory, or relocate auth-dir to a writable path.","Remove the trailing slash / directory occupying the file path.","For SELinux, adjust the label (`chcon -t container_file_t` or policy) or run with the proper context.","On NFS root_squash mounts, ensure the UID maps to a writable identity."],"exampleFix":"# before: auth-dir: /mnt/nfs/auths/  (root_squash denies app user)\n# after: auth-dir: /var/lib/cliproxy/auths (local writable volume)","handlingStrategy":"validation","validationCode":"// Verify the exact file path is creatable before the flow starts\nf, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o600)\nif err != nil { return err }\n_ = f.Close()","typeGuard":null,"tryCatchPattern":"if err := ts.SaveTokenToFile(path); err != nil {\n    if strings.Contains(err.Error(), \"failed to create token file\") {\n        // permission/SELinux/path-is-dir: fix fs, then re-run save; token data is still in memory\n    }\n}","preventionTips":["Run the process as a user with write access to auth-dir.","Do not end auth-dir paths with a slash or point them at directories.","Check SELinux/AppArmor policies for container workloads."],"tags":["filesystem","permissions","storage","codex","auth-flow"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}