alibaba/open-code-review · error

marshal config: %w

Error message

marshal config: %w

What it means

saveConfig serializes the Config struct with json.MarshalIndent; if marshaling fails, the error is wrapped as "marshal config". For this plain config struct this is rare — it would indicate a value JSON cannot represent (e.g. an unsupported type such as a channel/func field, or NaN via a custom marshaler).

Source

Thrown at cmd/opencodereview/provider_cmd.go:426

	}
	cfg.Model = selectedModel

	if err := saveConfig(configPath, cfg); err != nil {
		return err
	}

	fmt.Printf("\nModel set to: %s\n", selectedModel)
	return nil
}

func saveConfig(path string, cfg *Config) error {
	dir := filepath.Dir(path)
	if err := os.MkdirAll(dir, 0o755); err != nil {
		return fmt.Errorf("create config dir: %w", err)
	}
	data, err := json.MarshalIndent(cfg, "", "    ")
	if err != nil {
		return fmt.Errorf("marshal config: %w", err)
	}
	if err := os.WriteFile(path, data, 0o600); err != nil {
		return fmt.Errorf("write config: %w", err)
	}
	if err := os.Chmod(path, 0o600); err != nil {
		return fmt.Errorf("chmod config: %w", err)
	}
	return nil
}

func maskKey(key string) string {
	if key == "" {
		return "(not set)"
	}
	if len(key) <= 8 {
		return "***"
	}
	return key[:4] + "***" + key[len(key)-4:]

View on GitHub (pinned to 5cf97d0d15)

Solutions

  1. Inspect the wrapped inner error to find the offending field/value
  2. Check recently added Config/ProviderEntry fields for unsupported types (chan, func, complex)
  3. Remove or fix the offending value in the config structure
  4. Report/upstream if it is a serialization bug in the tool

Example fix

// before: field that cannot marshal
type Config struct { Hooks chan string `json:"hooks"` }
// after: marshalable representation
type Config struct { Hooks []string `json:"hooks"` }
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: ensure the struct round-trips
if _, err := json.Marshal(cfg); err != nil {
    return fmt.Errorf("config not serializable: %w", err)
}

Try / catch

if err := saveConfig(path, cfg); err != nil {
    var ute *json.UnsupportedTypeError
    if errors.As(err, &ute) {
        fmt.Fprintf(os.Stderr, "field %s cannot be marshaled\n", ute.Value)
    }
    return err
}

Prevention

When it happens

Trigger: saveConfig invoked (config set/unset commands, provider/model TUI saves) when json.MarshalIndent(cfg) fails — practically only if the Config struct gains a field of an unmarshalable type or a custom MarshalJSON returns an error.

Common situations: A newly added config field of unsupported type; corrupted in-memory config built from unusual inputs; a bug in a custom marshaler for a provider entry.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of alibaba/open-code-review@5cf97d0d15 (2026-09-02). Data as JSON: /api/errors/11f0b1fa78eaf5b2. Report an issue: GitHub.