pulumi/pulumi · error

first path segement of config key must be a string

Error message

first path segement of config key must be a string

What it means

parseKeyPath takes the first parsed path segment and uses it as the new config key's name. Since config keys are named by strings, the first segment must be a string; if the strict parser produced a non-string first accessor (e.g. an integer), this error is returned. (Note: the message contains the known typo "segement".)

Source

Thrown at sdk/go/common/resource/config/map.go:345

	return nil
}

// parseKeyPath returns the property paths in the key and a new config key with the first
// path segment as the name.
func parseKeyPath(k Key) (resource.PropertyPath, Key, error) {
	// Parse the path, which will be in the name portion of the key.
	p, err := resource.ParsePropertyPathStrict(k.Name())
	if err != nil {
		return nil, Key{}, fmt.Errorf("invalid config key path: %w", err)
	}
	if len(p) == 0 {
		return nil, Key{}, errors.New("empty config key path")
	}

	// Create a new key that has the first path segment as the name.
	firstKey, ok := p[0].(string)
	if !ok {
		return nil, Key{}, errors.New("first path segement of config key must be a string")
	}
	if firstKey == "" {
		return nil, Key{}, errors.New("config key is empty")
	}

	configKey := MustMakeKey(k.Namespace(), firstKey)

	return p, configKey, nil
}

View on GitHub (pinned to 793f7b2e16)

Solutions

  1. Make the first path segment a property name, e.g. use `list[0]` instead of `[0]`
  2. If you need array roots, nest them under a named key so the first accessor is a string
  3. Validate with resource.ParsePropertyPathStrict and assert the first element is a string before calling the Map API

Example fix

// before
k := config.MustMakeKey("app", "[0].port") // first accessor is an int
// after
k := config.MustMakeKey("app", "ports[0]") // first accessor is a string
Defensive patterns

Strategy: validation

Validate before calling

p, err := resource.ParsePropertyPathStrict(keyName)
if err != nil { return err }
if _, ok := p[0].(string); !ok {
    return fmt.Errorf("config key %q must start with a property name, not an index", keyName)
}

Type guard

func startsWithStringSeg(p resource.PropertyPath) bool {
    _, ok := p[0].(string)
    return len(p) > 0 && ok
}

Try / catch

if err != nil && strings.Contains(err.Error(), "must be a string") { /* rewrite path so first segment is a name */ }

Prevention

When it happens

Trigger: Using a key name whose first path accessor is an index rather than a property name, e.g. a key named `[0].sub` or `[42]` — ParsePropertyPathStrict succeeds (it is a valid path) but p[0] is an int.

Common situations: Mistakenly putting an array index at the root of a config key path; generating keys programmatically where a numeric segment lands first; misunderstanding that the root must always be a named property.

Related errors


AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31). Data as JSON: /api/errors/a2c3602a02df7125. Report an issue: GitHub.