anomalyco/sst · error

failed to decode SSM parameter value: %w

Error message

failed to decode SSM parameter value: %w

What it means

During the old-bootstrap cleanup migration step, SST reads the legacy `/sst/bootstrap/asset` SSM parameter and JSON-decodes its value into a struct with a `bucket` field. If the parameter's value is not valid JSON (or lacks the expected shape), `json.Unmarshal` fails and this error wraps it. It indicates the stored bootstrap metadata is malformed.

Source

Thrown at pkg/project/provider/aws.go:406

		ssmKey := "/sst/bootstrap/asset"
		getParamOutput, err := ssmClient.GetParameter(ctx, &ssm.GetParameterInput{
			Name: aws.String(ssmKey),
		})
		if err != nil {
			var paramNotFound *ssmTypes.ParameterNotFound
			if errors.As(err, &paramNotFound) {
				// Parameter doesn't exist, nothing to do
				return nil
			}
			return err
		}

		// Parameter exists, decode the value
		var value struct {
			Bucket string `json:"bucket"`
		}
		if err := json.Unmarshal([]byte(*getParamOutput.Parameter.Value), &value); err != nil {
			return fmt.Errorf("failed to decode SSM parameter value: %w", err)
		}

		if value.Bucket != "" && value.Bucket != data.Asset {
			// Empty the current asset bucket
			var continuationToken *string
			for {
				listObjectsInput := &s3.ListObjectsV2Input{
					Bucket: aws.String(data.Asset),
				}
				if continuationToken != nil {
					listObjectsInput.ContinuationToken = continuationToken
				}

				listObjectsOutput, err := s3Client.ListObjectsV2(ctx, listObjectsInput)
				if err != nil {
					if strings.Contains(err.Error(), "NoSuchBucket") {
						break
					}

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Open the AWS SSM console (or `aws ssm get-parameter --name /sst/bootstrap/asset`) and inspect the value
  2. If the value is not `{"bucket":"<name>"}` JSON, fix it or delete the parameter — cleanup treats a missing parameter as a no-op and proceeds
  3. Re-run `sst deploy` after correcting/deleting the parameter

Example fix

// before (corrupt SSM value)
my-old-asset-bucket
// after
{"bucket":"my-old-asset-bucket"}
Defensive patterns

Strategy: validation

Validate before calling

out, err := ssmClient.GetParameter(ctx, &ssm.GetParameterInput{Name: aws.String("/sst/bootstrap/asset")})
if err == nil {
    var v struct{ Bucket string `json:"bucket"` }
    if json.Unmarshal([]byte(*out.Parameter.Value), &v) != nil || v.Bucket == "" {
        // malformed metadata: delete the parameter so cleanup treats it as no-op
        ssmClient.DeleteParameter(ctx, &ssm.DeleteParameterInput{Name: aws.String("/sst/bootstrap/asset")})
    }
}

Type guard

func isValidBootstrapParam(raw string) bool {
    var v struct{ Bucket string `json:"bucket"` }
    return json.Unmarshal([]byte(raw), &v) == nil && v.Bucket != ""
}

Prevention

When it happens

Trigger: Running `sst deploy`/upgrade triggers the cleanup step when `/sst/bootstrap/asset` exists but its value is not valid JSON of `{"bucket":"..."}` — e.g. manually edited parameter, truncated value, or a value written by a tool other than SST.

Common situations: Hand-editing the SSM parameter in the console; an interrupted or partially failed older bootstrap write; another team/tool reusing the same parameter path with non-JSON content.

Understand the failure class

Related errors


AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30). Data as JSON: /api/errors/22a25035b7e04aac. Report an issue: GitHub.