{"record":{"id":"0a17611721717d42","repo":"chenhg5/cc-connect","slug":"weixin-create-state-dir-w","errorCode":null,"errorMessage":"weixin: create state dir: %w","messagePattern":"weixin: create state dir: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/weixin/weixin.go","lineNumber":274,"sourceCode":"\t\tallowFrom:       allowFrom,\n\t\trouteTag:        routeTag,\n\t\tstateDir:        stateDir,\n\t\tlongPollMS:      lp,\n\t\taccountLabel:    accountLabel,\n\t\thttpClient:      httpClient,\n\t\tcdnHttpClient:   cdnHttpClient,\n\t\ttokens:          make(map[string]string),\n\t\tdedupEnabled:    dedupEnabled,\n\t\tdedup:           core.NewMessageDedup(time.Duration(dedupWindow) * time.Second),\n\t\ttypingTickets:   make(map[string]typingTicketEntry),\n\t\tsendQuotaLimit:  burstLimit,\n\t\tsendQuotaWindow: time.Duration(burstWindow) * time.Second,\n\t}\n\tp.api = newAPIClient(baseURL, token, routeTag, httpClient)\n\n\tif stateDir != \"\" {\n\t\tif err := os.MkdirAll(stateDir, 0o755); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"weixin: create state dir: %w\", err)\n\t\t}\n\t\tp.syncBufPath = filepath.Join(stateDir, \"get_updates.buf\")\n\t\tp.tokensPath = filepath.Join(stateDir, \"context_tokens.json\")\n\t\tp.loadSyncBuf()\n\t\tp.loadTokens()\n\t}\n\n\treturn p, nil\n}\n\nfunc pickInt(v any) int {\n\tswitch x := v.(type) {\n\tcase int:\n\t\treturn x\n\tcase int64:\n\t\treturn int(x)\n\tcase float64:\n\t\treturn int(x)","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/weixin/weixin.go#L256-L292","documentation":"New creates the persistence directory given by the \"state_dir\" option using os.MkdirAll. If directory creation fails (permissions, read-only filesystem, path is a file), the error is wrapped and platform construction fails.","triggerScenarios":"weixin.New with a non-empty state_dir that cannot be created: parent directories not writable, the path exists as a regular file, disk full, or SELinux/container read-only mount.","commonSituations":"Running in a read-only container filesystem with default state dir; state_dir points into a root-owned directory while the bot runs unprivileged; a stale file occupies the state_dir path; typo in path so MkdirAll tries to create dirs under an invalid parent.","solutions":["Fix filesystem permissions on the state_dir parent or run as a user with write access","Ensure state_dir is not an existing regular file; remove/rename it","Point state_dir to a writable location (e.g. /var/lib/cc-connect or a volume)","Check the wrapped inner error (ENOENT/EACCES/ENOTDIR) for the exact cause"],"exampleFix":"// before\n\"state_dir\": \"/etc/cc-connect/state\"   // root-owned, read-only for the bot user\n// after\n\"state_dir\": \"/var/lib/cc-connect/weixin-state\"   // owned by the bot user","handlingStrategy":"validation","validationCode":"if sd, _ := opts[\"state_dir\"].(string); sd != \"\" {\n    if fi, err := os.Stat(sd); err == nil && !fi.IsDir() {\n        return fmt.Errorf(\"state_dir %s is not a directory\", sd)\n    }\n    if err := os.MkdirAll(sd, 0o755); err != nil {\n        return fmt.Errorf(\"cannot create state_dir %s: %w\", sd, err)\n    }\n}","typeGuard":null,"tryCatchPattern":"p, err := weixin.New(opts)\nif err != nil && strings.Contains(err.Error(), \"create state dir\") {\n    log.Error(\"state dir unwritable; check permissions/mount\", \"err\", err)\n    return err\n}","preventionTips":["Point state_dir at a writable volume in containers","Ensure the bot user owns the directory","Don't let a file occupy the state_dir path","Probe writability at startup"],"tags":["go","filesystem","weixin","permissions"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}