pulumi/pulumi · error

malformed resource reference: packageVersion must be a strin

Error message

malformed resource reference: packageVersion must be a string

What it means

A resource-reference property value (ResourceReferenceSig) contains a "packageVersion" field that is not a JSON string. The deserializer requires it be a string semver and throws this error.

Source

Thrown at pkg/resource/stack/deployment.go:1117

					plaintext, plainOk := objmap["plaintext"].(string)
					if (!cipherOk && !plainOk) || (plainOk && cipherOk) {
						return resource.PropertyValue{}, errors.New(
							"malformed secret value: exactly one of `ciphertext` or `plaintext` must be supplied",
						)
					}
					secret := &apitype.SecretV1{
						Sig:        resource.SecretSig,
						Plaintext:  plaintext,
						Ciphertext: ciphertext,
					}
					return deserializeSecret(ctx, secret, dec)
				case resource.ResourceReferenceSig:
					var packageVersion string
					if packageVersionV, ok := objmap["packageVersion"]; ok {
						packageVersion, ok = packageVersionV.(string)
						if !ok {
							return resource.PropertyValue{},
								errors.New("malformed resource reference: packageVersion must be a string")
						}
					}

					urnStr, ok := objmap["urn"].(string)
					if !ok {
						return resource.PropertyValue{}, errors.New("malformed resource reference: missing urn")
					}
					urn := resource.URN(urnStr)

					// deserializeID handles two cases, one of which arose from a bug in a refactoring of resource.ResourceReference.
					// This bug caused the raw ID PropertyValue to be serialized as a map[string]any. In the normal case, the
					// ID is serialized as a string.
					deserializeID := func() (string, bool, error) {
						idV, ok := objmap["id"]
						if !ok {
							return "", false, nil
						}

View on GitHub (pinned to 793f7b2e16)

Solutions

  1. Change packageVersion to a string (e.g. "5.0.0") in the serialized property
  2. Remove packageVersion entirely if the version is unknown
  3. Regenerate the deployment/state via official Pulumi tooling

Example fix

// before
{"sig":"...", "urn":"...", "packageVersion": 5}
// after
{"sig":"...", "urn":"...", "packageVersion": "5.0.0"}
Defensive patterns

Strategy: type-guard

Validate before calling

if pv, ok := objmap["packageVersion"]; ok {
	if _, isStr := pv.(string); !isStr {
		return errors.New("packageVersion must be a string")
	}
}

Type guard

func hasStringPackageVersion(m map[string]any) bool {
	v, ok := m["packageVersion"]; if !ok { return true }; _, isStr := v.(string); return isStr
}

Prevention

When it happens

Trigger: Deserializing a PropertyValue with resource-reference signature whose objmap["packageVersion"] is a number, object, or other non-string JSON value.

Common situations: JSON tooling writing numeric versions (e.g. 3 instead of "3.0.0"), hand-edited state, or buggy third-party generators of deployment documents.

Understand the failure class

Related errors


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