sipeed/picoclaw · error

model_name is required: %#v

Error message

model_name is required: %#v

What it means

Thrown by mergeModelListsWithMap when an array-style model_list entry is a map that has no model_name key at all. model_name is mandatory because the merge builds indexed keys ("name", "name:0", "name:1") from it to locate the matching security entries; without it the entry cannot be keyed, so the merge aborts and prints the whole offending map via %#v.

Source

Thrown at pkg/config/migration.go:515

func mergeModelListsWithMap(mainML []any, secML map[string]any) error {
	// Build indexed keys like toNameIndex does
	indexedKeys := make(map[string]int)
	countMap := make(map[string]int)
	for i, m := range mainML {
		if mVal, ok := m.(map[string]any); ok {
			if name, hasName := mVal["model_name"]; hasName {
				nameStr, ok := name.(string)
				if !ok {
					return fmt.Errorf("model_name must be a string, got %T", name)
				}
				index := countMap[nameStr]
				indexedKeys[fmt.Sprintf("%s:%d", nameStr, index)] = i
				if _, ok := indexedKeys[nameStr]; !ok {
					indexedKeys[nameStr] = i
				}
				countMap[nameStr]++
			} else {
				return fmt.Errorf("model_name is required: %#v", mVal)
			}
		}
	}

	for k, v := range secML {
		if i, ok := indexedKeys[k]; ok {
			if vv, ok := v.(map[string]any); ok {
				if mVal, ok := mainML[i].(map[string]any); ok {
					mVal["api_keys"] = vv["api_keys"]
				}
			}
		} else {
			logger.Warnf("model_name not found in main config: %s", k)
		}
		delete(secML, k)
	}

	return nil

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Add a model_name string to every entry shown in the %#v dump in the error message
  2. If the field was misnamed (e.g. `name:`), rename it to model_name
  3. Validate the whole list for missing keys before re-running (see validationCode in defense)

Example fix

# before
model_list:
  - provider: openai
    api_key: sk-...

# after
model_list:
  - model_name: gpt-4o
    provider: openai
    api_key: sk-...
Defensive patterns

Strategy: validation

Validate before calling

// Require model_name on every array-style entry before merge.
func validateModelListKeys(ml []any) error {
	for i, m := range ml {
		entry, ok := m.(map[string]any)
		if !ok { continue }
		if _, has := entry["model_name"]; !has {
			return fmt.Errorf("model_list[%d] (%v): model_name is required", i, entry)
		}
	}
	return nil
}

Type guard

func hasModelName(m any) bool {
	entry, ok := m.(map[string]any)
	if !ok { return false }
	_, has := entry["model_name"]
	return has
}

Try / catch

if err := mergeModelListsWithMap(mainML, secML); err != nil {
	// %#v in the message shows the offending entry — use it to locate the line in the YAML.
	log.Printf("migration failed on entry: %v", err)
	return err
}

Prevention

When it happens

Trigger: A model_list entry like `- provider: openai` or `- api_keys: [...]` that omits model_name. Any map entry lacking the key hits the else branch and the entire map is dumped in the error message.

Common situations: Renamed field (e.g. `name:` or `model:` instead of `model_name:`), truncated entries from hand-editing, or tooling that emits entries with only provider/credential fields. Appears during config migration when merging main config with a map-style security model_list.

Related errors


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