anomalyco/sst · critical

panic(err)

Error message

panic(err)

What it means

The SST Go SDK loads linked-resource metadata from SST_RESOURCE_* environment variables at package init (via loadFromEnv). Each variable's value must be a JSON object; if json.Unmarshal fails, the SDK panics — because init() cannot return errors, malformed resource data is treated as fatal at process start.

Source

Thrown at sdk/golang/resource/resource.go:99

		return nil, ErrNotFound
	}
	next, ok := casted[path[0]]
	if !ok {
		return nil, ErrNotFound
	}
	return get(next, path[1:]...)
}

func loadFromEnv() {
	for _, item := range os.Environ() {
		pair := strings.SplitN(item, "=", 2)
		key := pair[0]
		value := pair[1]
		if strings.HasPrefix(key, "SST_RESOURCE_") {
			var result map[string]interface{}
			err := json.Unmarshal([]byte(value), &result)
			if err != nil {
				panic(err)
			}
			resources[strings.TrimPrefix(key, "SST_RESOURCE_")] = result
		}
	}

	// Load consolidated resources JSON (used on Windows to avoid uppercasing)
	if consolidated := os.Getenv("SST_RESOURCES_JSON"); consolidated != "" {
		var parsed map[string]interface{}
		if err := json.Unmarshal([]byte(consolidated), &parsed); err == nil {
			for k, v := range parsed {
				resources[k] = v
			}
		}
	}
}

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Re-run your function through `sst dev` or a fresh `sst deploy` so SST regenerates the SST_RESOURCE_* variables from real resource outputs instead of hand-editing them
  2. Validate the value is a JSON object: `echo "$SST_RESOURCE_MY_BUCKET" | jq -e 'type == "object"'` before starting the app
  3. Fix shell quoting — single-quote the JSON: `export SST_RESOURCE_MY_BUCKET='{"BucketName":"..."}'`
  4. Check the linked resource's properties in sst.config.ts; only JSON-serializable plain objects can be linked
  5. Wrap the SDK import path: if you cannot fix the env, unset offending SST_RESOURCE_* vars (the SDK skips them), though linked-resource Lookups will fail

Example fix

// before
export SST_RESOURCE_MY_BUCKET={"BucketName": "my-bucket"}
// shell strips braces -> invalid JSON -> panic
// after
export SST_RESOURCE_MY_BUCKET='{"BucketName": "my-bucket"}'
Defensive patterns

Strategy: validation

Validate before calling

import "encoding/json"
import "os"
import "strings"

func validateSSTResourceEnv() error {
    for _, item := range os.Environ() {
        pair := strings.SplitN(item, "=", 2)
        if strings.HasPrefix(pair[0], "SST_RESOURCE_") {
            var m map[string]any
            if err := json.Unmarshal([]byte(pair[1]), &m); err != nil {
                return fmt.Errorf("%s is not a JSON object: %w", pair[0], err)
            }
        }
    }
    return nil
}

Try / catch

// SDK panics inside init(); you cannot catch it in-process — run the validator in a pre-launch check and fail fast with a clear message:
if err := validateSSTResourceEnv(); err != nil {
    log.Fatalf("aborting before SST SDK init: %v", err)
}

Prevention

When it happens

Trigger: Any program importing sdk/golang/resource where some environment variable prefixed with SST_RESOURCE_ (e.g. SST_RESOURCE_MY_BUCKET) contains a value that is not a valid JSON object — truncated JSON, single quotes instead of double quotes, plain strings/numbers, or a JSON array.

Common situations: Manually exporting a resource var in a shell where quoting mangles the JSON (`export SST_RESOURCE_X={"arn":...}` — the shell strips the braces); copying an env var through CI systems that escape quotes; defining a link in sst.config.ts whose value is not a plain JSON object; Windows env-var size mangling.

Related errors


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