{"record":{"id":"d28b3228b6e76886","repo":"chenhg5/cc-connect","slug":"save-provider-model-q-w","errorCode":null,"errorMessage":"save provider model %q: %w","messagePattern":"save provider model %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/engine.go","lineNumber":9985,"sourceCode":"\t\t\t}\n\t\t}\n\t\tswitcher.SetModel(target)\n\t\treturn target, nil\n\t}\n\n\tproviders := providerSwitcher.ListProviders()\n\tupdated, found := SetProviderModel(providers, active.Name, target)\n\tif !found {\n\t\tswitcher.SetModel(target)\n\t\treturn target, nil\n\t}\n\tif !persistConfig {\n\t\tswitcher.SetModel(target)\n\t\treturn target, nil\n\t}\n\tif persistConfig && e.providerModelSaveFunc != nil {\n\t\tif err := e.providerModelSaveFunc(active.Name, target); err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"save provider model %q: %w\", active.Name, err)\n\t\t}\n\t}\n\tproviderSwitcher.SetProviders(updated)\n\tswitcher.SetModel(target)\n\tproviderSwitcher.SetActiveProvider(active.Name)\n\treturn target, nil\n}\n\nfunc (e *Engine) cmdReasoning(p Platform, msg *Message, args []string) {\n\tagent, sessions, _, err := e.commandContext(p, msg)\n\tif err != nil {\n\t\te.reply(p, msg.ReplyCtx, e.i18n.Tf(MsgWsResolutionError, err))\n\t\treturn\n\t}\n\n\tswitcher, ok := agent.(ReasoningEffortSwitcher)\n\tif !ok {\n\t\te.reply(p, msg.ReplyCtx, e.i18n.T(MsgReasoningNotSupported))","sourceCodeStart":9967,"sourceCodeEnd":10003,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/core/engine.go#L9967-L10003","documentation":"Error from the ProviderSwitcher path of model switching: after updating the provider's model list, the engine calls `e.providerModelSaveFunc(active.Name, target)` to persist which model is active for which provider; any failure is wrapped as \"save provider model %q: %w\". The in-memory switch still succeeded; only the durable save failed.","triggerScenarios":"/model or /provider switch on an agent implementing ProviderSwitcher with persistConfig=true, where providerModelSaveFunc errors: cannot write the config file, provider name contains characters that break serialization, or the config backend rejects the update.","commonSituations":"Read-only config mount in Docker/K8s; SELinux or ACL blocking the write; concurrent edits to config.toml causing a write conflict; provider name with characters unsupported by the save backend.","solutions":["Make the config file writable (permissions, mount flags, SELinux context)","Inspect the wrapped inner error for the backend's specific failure","Avoid concurrent model switches from multiple chats writing the same config","Use a non-persisting switch (persistConfig=false) as a temporary workaround"],"exampleFix":"// before: k8s volume mounted read-only\nvolumeMounts:\n  - mountPath: /root/.config/cc-connect\n    readOnly: true\n\n// after: writable config volume\nvolumeMounts:\n  - mountPath: /root/.config/cc-connect\n    readOnly: false","handlingStrategy":"validation","validationCode":"f, err := os.OpenFile(cfgPath, os.O_APPEND|os.O_WRONLY, 0); if err != nil { return fmt.Errorf(\"provider model save will fail, config unwritable: %w\", err) }; f.Close()","typeGuard":null,"tryCatchPattern":"if _, err := e.SwitchProviderModel(provider, model); err != nil { slog.Warn(\"provider model not persisted\", \"provider\", provider, \"err\", err); /* retry with persistConfig=false */ }","preventionTips":["Verify the config backend is writable (mount flags, SELinux/ACLs) before enabling persisted provider switching","Avoid issuing provider/model switches concurrently from multiple chats","Use simple provider names without characters your config backend mishandles","Read the wrapped (%w) cause to pinpoint filesystem vs backend failure"],"tags":["go","persistence","config","provider-switch"],"backgroundTag":"file-write-failed","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"}