Netflix/chaosmonkey · error

non-string in %v

Error message

non-string in %v

What it means

Type guard in toStrings: while converting a config list to []string, an element was not a string (e.g. a TOML integer or boolean inside the accounts/trackers list), so the whole conversion aborts with the offending list included.

Source

Thrown at config/monkey.go:254

}

// Accounts return a list of accounts where Choas Monkey is enabled
func (m *Monkey) Accounts() ([]string, error) {
	err := m.readRemoteConfig()
	if err != nil {
		return nil, err
	}

	return m.getStringSlice(param.Accounts)
}

// toStrings converts a slice of interfaces to a slice of strings
func toStrings(values []interface{}) ([]string, error) {
	result := make([]string, len(values))
	for i, x := range values {
		x, valid := x.(string)
		if !valid {
			return nil, errors.Errorf("non-string in %v", values)
		}
		result[i] = x
	}
	return result, nil
}

// StartHour (o'clock) is when Chaos
// Monkey starts terminating this value is in [0,23] This is time-zone
// dependent, see the Location method
func (m *Monkey) StartHour() int { return m.v.GetInt(param.StartHour) }

// EndHour (o'clock) is the time after which Chaos Monkey will
// not terminate instances.
// this value is in [0,23]
// This is time-zone dependent, see the Location method
func (m *Monkey) EndHour() int {
	return m.v.GetInt(param.EndHour)
}

View on GitHub (pinned to eaa28fb761)

Solutions

  1. Quote every element in the config array as a string
  2. Check the printed %v values to find the non-string element
  3. Coerce/normalize values (e.g. strconv) if the config legitimately holds numbers
  4. Add a validation step when the config is written, not just read

Example fix

// before
team = [alice, 42, bob]
// after
team = ["alice", "42", "bob"]
Defensive patterns

Strategy: validation

Validate before calling

// before calling getStringSlice, ensure all array entries are quoted strings in TOML:
// team = ["alice", "bob"]  — not  team = [alice, bob]
// or sanitize:
for _, v := range raw.([]interface{}) {
    if _, ok := v.(string); !ok {
        return fmt.Errorf("config array contains non-string: %v", v)
    }
}

Type guard

func allStrings(values []interface{}) bool {
    for _, v := range values {
        if _, ok := v.(string); !ok {
            return false
        }
    }
    return true
}

Try / catch

apps, err := cfg.getStringSlice("apps")
if err != nil {
    log.Printf("fix the config array, all entries must be quoted strings: %v", err)
    return err
}

Prevention

When it happens

Trigger: Calling getStringSlice for a config key whose value mixes types, e.g. ["app1", 42] or a TOML array with non-string entries.

Common situations: Config arrays like team emails or app lists where someone wrote an unquoted number/bool; viper returning heterogeneous []interface{} from YAML/JSON.

Related errors


AI-assisted analysis of Netflix/chaosmonkey@eaa28fb761 (2026-09-03). Data as JSON: /api/errors/edd423806f44babe. Report an issue: GitHub.