pulumi/pulumi · error
'%s' must be of type string
Error message
'%s' must be of type string
What it means
GetProviderParameterization reads '__internal.parameterization', a base64-encoded string encoding the provider's parameterization spec, and requires it to be a string. The engine throws this when the value is a non-string type, since the base64 payload can only be carried as a string.
Source
Thrown at pkg/resource/deploy/providers/registry.go:322
}
// GetProviderParameterization fetches and parses a provider parameterization from the given property map. If the
// parameterization property is not present, this function returns nil.
func GetProviderParameterization(
name tokens.Package, inputs resource.PropertyMap,
) (*workspace.Parameterization, error) {
internalInputs, err := getInternal(inputs)
if err != nil {
return nil, err
}
parameter, ok := internalInputs[parameterizationKey]
if !ok {
return nil, nil
}
if !parameter.IsString() {
return nil, fmt.Errorf("'%s' must be of type string", parameterizationKey)
}
bytes, err := base64.StdEncoding.DecodeString(parameter.StringValue())
if err != nil {
return nil, fmt.Errorf("could not decode base64 parameter value: %w", err)
}
version, ok := inputs["version"]
if !ok {
return nil, errors.New("must have a 'version' field")
}
if !version.IsString() {
return nil, errors.New("must have a 'version' field of type string")
}
sv, err := semver.Parse(version.StringValue())
if err != nil {
return nil, fmt.Errorf("could not parse provider version: %w", err)
}
View on GitHub (pinned to 793f7b2e16)
Solutions
- Restore __internal.parameterization to its base64 string form (as written when the provider was created) via stack export/import
- Remove the parameterization key only if the provider truly is not parameterized — otherwise recreate the provider resource
- Regenerate the base64 value from the correct parameterization spec and write it back as a string
- Upgrade the CLI/provider if a version mismatch rewrote state incorrectly
Example fix
// before
"__internal": { "parameterization": { "name": "aws", "version": "1.0.0" } }
// after
"__internal": { "parameterization": "eyJuYW1lIjoiYXdzIiwidmVyc2lvbiI6IjEuMC4wIn0=" } Defensive patterns
Strategy: type-guard
Validate before calling
if p, ok := internalInputs["parameterization"]; ok && !p.IsString() {
return fmt.Errorf("parameterization must be a base64 string, got %s", p.TypeString())
} Type guard
func isBase64String(v resource.PropertyValue) bool {
if !v.IsString() { return false }
_, err := base64.StdEncoding.DecodeString(v.StringValue())
return err == nil
} Prevention
- Never hand-edit the base64 parameterization blob; recreate the provider instead
- Use base64.StdEncoding.EncodeToString to build the value, never ad-hoc encodings
- Keep parameterized providers managed by the engine so __internal stays consistent
When it happens
Trigger: __internal.parameterization is a number, bool, array, or object in the provider's inputs, typically from corrupted or hand-modified state.
Common situations: Hand-edited state; tooling or migrations that re-encoded the base64 blob into another type; custom parameterized-provider code writing raw objects instead of encoding to base64.
Related errors
- '%s[%s]' must be a string
- '%s' must be a string
- malformed byte string for %q: value is not a string
- fromBase64 data argument must be a string
- ignoreChanges must be an array of strings
AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31).
Data as JSON: /api/errors/f564d6eb8014466a.
Report an issue: GitHub.