sipeed/picoclaw · error

turn_profile.%s.mode custom is not supported in this version

Error message

turn_profile.%s.mode custom is not supported in this version

What it means

Returned by validateTurnProfileBlock when a turn_profile block's effective mode is `custom` but that block does not allow custom profiles in this build. In the current code only `skills` and `tools` blocks pass allowCustom=true; `history` and `system_prompt` pass false, so `mode: custom` under turn_profile.history or turn_profile.system_prompt is rejected even though the custom mode exists elsewhere.

Source

Thrown at pkg/config/turn_profile.go:109

	if err := validateTurnProfileBlock("skills", profile.Skills, true); err != nil {
		return err
	}
	if err := validateTurnProfileBlock("tools", profile.Tools, true); err != nil {
		return err
	}
	return nil
}

func validateTurnProfileBlock(field string, block TurnProfileBlock, allowCustom bool) error {
	mode := block.Mode.Effective()
	switch mode {
	case TurnProfileModeDefault, TurnProfileModeOff:
		return nil
	case TurnProfileModeCustom:
		if allowCustom {
			return nil
		}
		return fmt.Errorf("turn_profile.%s.mode custom is not supported in this version", field)
	default:
		return fmt.Errorf("turn_profile.%s.mode has unsupported mode %q", field, block.Mode)
	}
}

func cleanStringList(values []string) []string {
	if len(values) == 0 {
		return nil
	}
	out := make([]string, 0, len(values))
	seen := make(map[string]struct{}, len(values))
	for _, value := range values {
		value = strings.TrimSpace(value)
		if value == "" {
			continue
		}
		if _, ok := seen[value]; ok {
			continue

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Remove `mode: custom` from the history/system_prompt block (let it default) or set an allowed mode
  2. Move the customization you wanted into a block that supports custom (skills, tools)
  3. Upgrade or check release notes if custom history/system_prompt is expected to be supported in a newer build
  4. Re-validate the config after the change

Example fix

# before
turn_profile:
  history:
    mode: custom

# after
turn_profile:
  history:
    mode: default
Defensive patterns

Strategy: validation

Validate before calling

// Reject custom mode for blocks that don't allow it, pre-load.
var customForbidden = map[string]bool{"history": true, "system_prompt": true}
func turnProfileModesOK(p TurnProfile) error {
	if customForbidden["history"] && p.History.Mode.Effective() == TurnProfileModeCustom {
		return fmt.Errorf("turn_profile.history: custom not supported")
	}
	if customForbidden["system_prompt"] && p.SystemPrompt.Mode.Effective() == TurnProfileModeCustom {
		return fmt.Errorf("turn_profile.system_prompt: custom not supported")
	}
	return nil
}

Type guard

func allowsCustom(block string) bool {
	switch block {
	case "skills", "tools":
		return true // allowCustom=true at call sites
	default: // history, system_prompt
		return false
	}
}

Try / catch

if err := cfg.Validate(); err != nil {
	if strings.Contains(err.Error(), "custom is not supported") {
		// strip mode: custom from history/system_prompt and retry
	}
	return err
}

Prevention

When it happens

Trigger: Config contains `turn_profile:\n history:\n mode: custom` or `turn_profile:\n system_prompt:\n mode: custom`. Block.Mode.Effective() resolves to TurnProfileModeCustom, allowCustom is false for those two blocks, and the error fires naming the field.

Common situations: Copying a skills/tools-style custom profile into history or system_prompt, or upgrading to a version where custom is gated per-block. Users assume `custom` is universally available because other blocks accept it.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/ac26b5166e80aff4. Report an issue: GitHub.