unionlabs/union · error

upgradeToTrigger is not of type string

Error message

upgradeToTrigger is not of type string

What it means

The last of getCommandArgs' assertions: server.KeyTriggerTestnetUpgrade must be present as a string (the upgrade name the local testnet should trigger, empty when unused). Missing option or wrong type panics. Note the next option, accounts-to-fund, is read with cast.ToString instead — showing the tolerant pattern these four panics do not use.

Source

Thrown at uniond/cmd/uniond/cmd/testnet.go:236

	newValAddr, ok := appOpts.Get(server.KeyNewValAddr).(bytes.HexBytes)
	if !ok {
		panic("newValAddr is not of type bytes.HexBytes")
	}
	args.newValAddr = newValAddr
	newValPubKey, ok := appOpts.Get(server.KeyUserPubKey).(crypto.PubKey)
	if !ok {
		panic("newValPubKey is not of type crypto.PubKey")
	}
	args.newValPubKey = newValPubKey
	newOperatorAddress, ok := appOpts.Get(server.KeyNewOpAddr).(string)
	if !ok {
		panic("newOperatorAddress is not of type string")
	}
	args.newOperatorAddress = newOperatorAddress
	upgradeToTrigger, ok := appOpts.Get(server.KeyTriggerTestnetUpgrade).(string)
	if !ok {
		panic("upgradeToTrigger is not of type string")
	}
	args.upgradeToTrigger = upgradeToTrigger

	// validate  and set accounts to fund
	accountsString := cast.ToString(appOpts.Get(flagAccountsToFund))

	for _, account := range strings.Split(accountsString, ",") {
		if account != "" {
			addr, err := sdk.AccAddressFromBech32(account)
			if err != nil {
				return args, fmt.Errorf("invalid bech32 address format %w", err)
			}
			args.accountsToFund = append(args.accountsToFund, addr)
		}
	}

	// home dir
	homeDir := cast.ToString(appOpts.Get(flags.FlagHome))

View on GitHub (pinned to 031785bb6d)

Solutions

  1. Run the standard `uniond testnet` command so all server.Key* flags are bound
  2. When constructing appOpts yourself, set an explicit value even if empty: viper.Set(server.KeyTriggerTestnetUpgrade, "")
  3. Check for typos/casing in option keys — appOpts.Get on a missing key returns nil and trips the assertion
  4. Fork-friendly change: read with cast.ToString and validate, mirroring the accounts-to-fund line below it
Defensive patterns

Strategy: type-guard

Validate before calling

vpr.Set(server.KeyTriggerTestnetUpgrade, "") // empty string is valid; absence (nil) panics

Type guard

func optTrigger(appOpts servertypes.AppOptions) (string, bool) {
	v, ok := appOpts.Get(server.KeyTriggerTestnetUpgrade).(string)
	return v, ok
}

Prevention

When it happens

Trigger: Programmatic testnet app construction without setting KeyTriggerTestnetUpgrade; a custom command dropping the flag binding; the value supplied as a non-string type in appOpts.

Common situations: Tests embedding the testnet runner; wrappers around the testnet command; option maps built from JSON where the field is absent or typed differently.

Related errors


AI-assisted analysis of unionlabs/union@031785bb6d (2026-08-16). Data as JSON: /api/errors/64070f54a0703911. Report an issue: GitHub.