{"record":{"id":"0982bd7656c841f8","repo":"router-for-me/CLIProxyAPI","slug":"failed-to-write-token-to-file-w","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/claude/token.go","lineNumber":101,"sourceCode":"\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}()\n\n\t// Encode and write the token data as JSON\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":83,"sourceCodeEnd":105,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/auth/claude/token.go#L83-L105","documentation":"The token file was created but json.NewEncoder(f).Encode(data) failed while serializing or writing the credential. Two distinct causes hide here: a JSON marshal error on the merged data (non-serializable field — same class as error 191) or an I/O write error (disk full, quota exceeded) since the encoder writes directly to the file.","triggerScenarios":"Merged token data contains a value JSON cannot marshal; or the filesystem fills up (ENOSPC), quota is hit, or the volume is yanked mid-write precisely between Create and Encode.","commonSituations":"Disk-full on small containers/VMs where auth-dir shares the root volume; embedding users adding func-typed exported fields to the storage struct; NFS quirks with delayed allocation; the defer-close then logs a secondary close error confirming a bad stream state.","solutions":["Check the wrapped error: *json.MarshalTypeError/UnsupportedTypeError → remove the non-serializable field (see error 191 fixes); 'no space left on device' → free space or move auth-dir to a bigger volume.","Validate serializability before saving with a json.Marshal of the merged data in a test.","Monitor disk usage on the auth-dir volume; keep credentials off the container root layer."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"data, err := misc.MergeMetadata(ts, ts.Metadata)\nif err != nil { return err }\nif _, err := json.Marshal(data); err != nil { return fmt.Errorf(\"credential not serializable: %w\", err) }","typeGuard":null,"tryCatchPattern":"if err := ts.SaveTokenToFile(p); err != nil {\n    if strings.Contains(err.Error(), \"failed to write token\") {\n        // distinguish disk-full from marshal failure via the wrapped error\n        if errors.Is(err, syscall.ENOSPC) { /* free space, retry */ } else { /* fix data model */ }\n    }\n}","preventionTips":["Pre-validate with json.Marshal before saving; monitor disk space on the auth-dir volume.","Keep credentials on a volume with headroom, not the container root layer."],"tags":["claude","storage","json","disk","filesystem"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}