{"record":{"id":"34effd0fb73bbd30","repo":"plandex-ai/plandex","slug":"error-updating-settings-v","errorCode":null,"errorMessage":"error updating settings: %v","messagePattern":"error updating settings: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/cli/lib/model_settings.go","lineNumber":216,"sourceCode":"// save settings in file to server\nfunc SyncPlanModelSettings() error {\n\tsettings, err := api.Client.GetSettings(CurrentPlanId, CurrentBranch)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting settings: %v\", err)\n\t}\n\n\tupdatedSettings, apiErr := ApplyModelSettings(GetPlanModelSettingsPath(CurrentPlanId), settings)\n\tif apiErr != nil {\n\t\treturn fmt.Errorf(\"error applying model settings: %v\", err)\n\t}\n\n\tres, updateErr := api.Client.UpdateSettings(CurrentPlanId, CurrentBranch, shared.UpdateSettingsRequest{\n\t\tModelPackName: updatedSettings.ModelPackName,\n\t\tModelPack:     updatedSettings.ModelPack,\n\t})\n\n\tif updateErr != nil {\n\t\treturn fmt.Errorf(\"error updating settings: %v\", err)\n\t}\n\n\tif res == nil {\n\t\treturn nil\n\t}\n\n\tfmt.Println(res.Msg)\n\n\treturn nil\n}\n\nfunc SyncDefaultModelSettings() error {\n\tsettings, err := api.Client.GetOrgDefaultSettings()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting settings: %v\", err)\n\t}\n\n\tupdatedSettings, apiErr := ApplyModelSettings(DefaultModelSettingsPath, settings)","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/cli/lib/model_settings.go#L198-L234","documentation":"SyncPlanModelSettings pushes the merged settings back to the server via api.Client.UpdateSettings. If UpdateSettings returns an error, this message is thrown. Note the code wraps `err` (the earlier GetSettings error variable, which is nil at this point) instead of `updateErr`, so the printed message will read 'error updating settings: %!v(<nil>)'-style — the real cause is hidden in updateErr.","triggerScenarios":"UpdateSettings fails: auth expired (401/403), plan/branch not found (404), request body rejected by validation (400), conflict from concurrent edits (409), network failure or timeout during the write.","commonSituations":"Another session updated settings concurrently causing a conflict; token expired mid-session after a long-running command; server rejects the custom model pack shape; offline/laptop sleep during sync.","solutions":["Fix the wrapping bug first: return `fmt.Errorf(\"error updating settings: %w\", updateErr)` so the real API error is visible.","Re-authenticate if the (now-visible) error is 401/403; re-run sync after login.","Re-fetch settings and re-apply if the error indicates a conflict — the server may have newer settings.","Check connectivity and retry; verify CurrentPlanId/CurrentBranch are valid for an update (404)."],"exampleFix":"// before (wraps stale/nil err)\nif updateErr != nil {\n    return fmt.Errorf(\"error updating settings: %v\", err)\n}\n// after\nif updateErr != nil {\n    return fmt.Errorf(\"error updating settings: %w\", updateErr)\n}","handlingStrategy":"try-catch","validationCode":"// pre-flight: confirm the target still exists server-side\nsettings, err := lib.Client.GetSettings(planID, branch)\nif err != nil {\n    return fmt.Errorf(\"cannot update settings for missing plan/branch: %w\", err)\n}\n_ = settings","typeGuard":"func isConflict(err error) bool { return err != nil && strings.Contains(err.Error(), \"409\") }","tryCatchPattern":"err := lib.SyncPlanModelSettings()\nif err != nil && strings.Contains(err.Error(), \"error updating settings\") {\n    // the library wraps the wrong (nil) variable — the real cause is hidden;\n    // re-fetch and retry, or upgrade the library for the updateErr wrap fix\n    if isConflict(err) { return refetchAndReapply() }\n    return retryWithBackoff(3, time.Second, lib.SyncPlanModelSettings)\n}","preventionTips":["Avoid concurrent syncs of the same plan from multiple machines.","Re-login if the session is long-lived; auth may expire mid-sync.","Upgrade/patch the library so updateErr (not err) is wrapped.","Retry once after re-fetching settings on suspected conflicts."],"tags":["go","api","wrapped-wrong-error","settings-sync"],"backgroundTag":"wrong-error-variable-wrapped","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}