{"record":{"id":"3085c010d153badd","repo":"router-for-me/CLIProxyAPI","slug":"failed-to-create-directory-v","errorCode":null,"errorMessage":"failed to create directory: %v","messagePattern":"failed to create directory: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/auth/claude/token.go","lineNumber":79,"sourceCode":"}\n\n// SaveTokenToFile serializes the Claude token storage to a JSON file.\n// This method creates the necessary directory structure and writes the token\n// data in JSON format to the specified file path for persistent storage.\n// It merges any injected metadata into the top-level JSON object.\n//\n// Parameters:\n//   - authFilePath: The full path where the token file should be saved\n//\n// Returns:\n//   - error: An error if the operation fails, nil otherwise\nfunc (ts *ClaudeTokenStorage) SaveTokenToFile(authFilePath string) error {\n\tmisc.LogSavingCredentials(authFilePath)\n\tts.Type = \"claude\"\n\n\t// Create directory structure if it doesn't exist\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\t// Create the token file\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(\"claude token storage: close token file error: %v\", errClose)\n\t\t}\n\t}()","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/auth/claude/token.go#L61-L97","documentation":"SaveTokenToFile creates the auth file's parent directory with 0700 before writing the persisted Claude credential. This error means os.MkdirAll failed, so the token was never written and the freshly obtained credential exists only in memory. The underlying %v tells you whether it is permissions, a path conflict, or an invalid path.","triggerScenarios":"auth-dir (default auths/) points to a location the process cannot create or write: permission denied, a path component that is a regular file, read-only filesystem, or an unset/relative path resolving somewhere unexpected.","commonSituations":"Running the binary as a different user than the one that owns the auths/ directory; auth-dir misconfigured in config.yaml to a file path or a root-owned location; container images with a read-only layer where auth-dir was not mounted; SELinux/AppArmor denials on the config directory.","solutions":["Check the wrapped OS error text: 'permission denied' → fix ownership/permissions of the parent directory (chown/chmod so the runtime user can write).","Verify auth-dir in config.yaml is a directory path that can be created (no file in its place) and is on a writable volume.","In containers, mount a writable volume at the configured auth-dir.","Relax SELinux/AppArmor policies if they are the denier (check audit logs)."],"exampleFix":"# before\nauth-dir: /var/lib/cliproxy/auths   # owned by root, server runs as app user\n\n# after\nsudo chown -R appuser /var/lib/cliproxy\nauth-dir: /var/lib/cliproxy/auths","handlingStrategy":"validation","validationCode":"dir := filepath.Dir(authFilePath)\nif info, err := os.Stat(dir); err == nil && !info.IsDir() {\n    return fmt.Errorf(\"auth path %s is a file, not a directory\", dir)\n}\nif err := os.WriteFile(filepath.Join(dir, \".probe\"), nil, 0600); err != nil {\n    return fmt.Errorf(\"auth dir not writable by this user: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := storage.SaveTokenToFile(path); err != nil && strings.Contains(err.Error(), \"failed to create directory\") {\n    // fix ownership/permissions of auth-dir, then re-save the in-memory credential\n}","preventionTips":["Run the process as a dedicated user that owns auth-dir.","Mount a writable volume at auth-dir in containers; verify with a write probe at startup."],"tags":["claude","storage","filesystem","permissions","auth"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}