plandex-ai/plandex · error
error unmarshalling plan settings: %v
Error message
error unmarshalling plan settings: %v
What it means
PlanSettings.DeepCopy wraps a failure from json.Unmarshal when decoding the marshalled copy back into a new PlanSettings. This means the marshalled JSON does not conform to PlanSettings' unmarshalling requirements (e.g. a field's UnmarshalJSON rejected the value, or type mismatch).
Source
Thrown at app/shared/plan_model_settings.go:246
func (ps PlanSettings) ForCompare() PlanSettings {
ps.UpdatedAt = time.Time{}
ps.CustomModelPacks = nil
ps.CustomModels = nil
ps.CustomProviders = nil
ps.IsCloud = false
ps.Configured = false
return ps
}
func (ps PlanSettings) DeepCopy() (*PlanSettings, error) {
bytes, err := json.Marshal(ps)
if err != nil {
return nil, fmt.Errorf("error marshalling plan settings: %v", err)
}
var copy PlanSettings
err = json.Unmarshal(bytes, ©)
if err != nil {
return nil, fmt.Errorf("error unmarshalling plan settings: %v", err)
}
return ©, nil
}
func getOptionalModelProviderOptions(settings *PlanSettings, cfg *ModelRoleConfig) ModelProviderOptions {
if cfg == nil {
return ModelProviderOptions{}
}
return cfg.GetModelProviderOptions(settings)
}
View on GitHub (pinned to e2d772072e)
Solutions
- Read the wrapped %v error to identify the failing field path from encoding/json
- Fix the custom UnmarshalJSON on the offending field to accept valid states or report clearer errors
- Since the bytes came from Marshal of the same struct, verify no field's UnmarshalJSON/MarshalJSON are asymmetric
- Round-trip test a fully populated PlanSettings in unit tests
Example fix
// before
func (t *T) UnmarshalJSON(b []byte) error { ... if bad { return errors.New("bad") } }
// after
func (t *T) UnmarshalJSON(b []byte) error { ... accept legacy shapes or return nil for empty } Defensive patterns
Strategy: try-catch
Validate before calling
func validateRoundTrip(ps shared.PlanSettings) error {
copy, err := ps.DeepCopy()
if err != nil { return err }
if copy == nil { return errors.New("nil copy") }
return nil
} Try / catch
copy, err := ps.DeepCopy()
if err != nil {
if strings.Contains(err.Error(), "unmarshalling") {
return fmt.Errorf("settings round-trip failed: %w", err)
}
return err
} Prevention
- Keep UnmarshalJSON implementations symmetric with MarshalJSON
- Accept legacy/empty payloads in custom UnmarshalJSON
- Test DeepCopy after every change to PlanSettings fields
When it happens
Trigger: DeepCopy is invoked via updateModelSettings / ApplyModelSettings and a field's custom UnmarshalJSON returns an error, or a UnmarshalJSON implementation writes into the receiver on invalid input during the marshal→unmarshal round trip.
Common situations: Custom UnmarshalJSON methods on PlanSettings fields that validate data and reject recently added or user-supplied values; mismatches introduced by version skew where the settings schema changed.
Related errors
- error marshalling plan settings: %v
- error marshalling models: %v
- error marshalling model pack: %v
- error marshalling current plan settings: %v
- error marshalling convo message: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/9d07b195d952cb38.
Report an issue: GitHub.