pulumi/pulumi · error

decoding APIVersionCapabilityConfig returned %w

Error message

decoding APIVersionCapabilityConfig returned %w

What it means

When Parse() encounters the APIVersion capability (version 1), it json.Unmarshals entry.Configuration into APIVersionCapabilityConfig. If the payload cannot be decoded, the failure is wrapped as "decoding APIVersionCapabilityConfig returned %w" and Parse() returns an empty Capabilities. It means the backend's API-version negotiation capability blob is not valid JSON for the expected struct.

Source

Thrown at sdk/go/common/apitype/service.go:207

				parsed.CopilotExplainPreviewV1 = true
			}
		case DeploymentSchemaVersion:
			if entry.Version == 1 {
				var versionConfig DeploymentSchemaVersionConfig
				if err := json.Unmarshal(entry.Configuration, &versionConfig); err != nil {
					return Capabilities{}, fmt.Errorf("decoding DeploymentSchemaVersionConfig returned %w", err)
				}
				parsed.DeploymentSchemaVersion = versionConfig.Version
			}
		case StackPolicyPacks:
			if entry.Version == 1 {
				parsed.StackPolicyPacks = true
			}
		case APIVersion:
			if entry.Version == 1 {
				var cfg APIVersionCapabilityConfig
				if err := json.Unmarshal(entry.Configuration, &cfg); err != nil {
					return Capabilities{}, fmt.Errorf("decoding APIVersionCapabilityConfig returned %w", err)
				}
				if err := cfg.validate(); err != nil {
					return Capabilities{}, fmt.Errorf("invalid APIVersionCapabilityConfig: %w", err)
				}
				parsed.APIVersion = &cfg
			}
		case NeoCLIMode:
			if entry.Version == 1 {
				var cfg NeoCLIModeConfig
				if err := json.Unmarshal(entry.Configuration, &cfg); err != nil {
					return Capabilities{}, fmt.Errorf("decoding NeoCLIModeConfig returned %w", err)
				}
				parsed.NeoCLIMode = &cfg
			}
		case BeginUpdate:
			if entry.Version == 1 {
				parsed.BeginUpdate = true
			}

View on GitHub (pinned to 793f7b2e16)

Solutions

  1. Inspect the raw Configuration JSON for the APIVersion entry and correct it to match APIVersionCapabilityConfig's fields and types.
  2. Print the Configuration bytes before parsing to identify the exact JSON defect.
  3. Align backend and CLI versions so the capability schema matches what the CLI unmarshals.
  4. In test fixtures, marshal a real APIVersionCapabilityConfig value with json.Marshal instead of hand-writing JSON strings.
  5. If API-version negotiation is not required, remove the malformed capability entry from the response.

Example fix

// before
cfg := APIVersionCapabilityConfig{}
if err := json.Unmarshal(entry.Configuration, &cfg); err != nil {
    return Capabilities{}, fmt.Errorf("decoding APIVersionCapabilityConfig returned %w", err)
}
// after (validate payload first)
if !json.Valid(entry.Configuration) {
    return Capabilities{}, fmt.Errorf("APIVersion capability configuration is not valid JSON: %s", entry.Configuration)
}
var cfg APIVersionCapabilityConfig
if err := json.Unmarshal(entry.Configuration, &cfg); err != nil {
    return Capabilities{}, fmt.Errorf("decoding APIVersionCapabilityConfig returned %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

func validAPIVersionConfig(raw json.RawMessage) bool {
	if !json.Valid(raw) {
		return false
	}
	var cfg apitype.APIVersionCapabilityConfig
	if err := json.Unmarshal(raw, &cfg); err != nil {
		return false
	}
	return cfg.validate() == nil
}

Type guard

func isAPIVersionDecodeError(err error) bool {
	return err != nil && strings.Contains(err.Error(), "decoding APIVersionCapabilityConfig returned")
}

Try / catch

caps, err := resp.Parse()
if err != nil {
	if isAPIVersionDecodeError(err) {
		// proceed without API-version negotiation
		caps.APIVersion = nil
		err = nil
	}
}
if err != nil {
	return err
}

Prevention

When it happens

Trigger: Calling CapabilitiesResponse.Parse() when the capabilities list contains Capability==APIVersion, Version==1, and Configuration is invalid JSON or has fields whose types do not match APIVersionCapabilityConfig (e.g. a string where a number range/object is expected).

Common situations: A backend advertises REST API version negotiation but sends a config payload from an incompatible schema version; proxy or test stubs hand-write the configuration string with syntax errors; schema drift between CLI and service versions.

Related errors


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