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
- 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
- Validate the value is a JSON object: `echo "$SST_RESOURCE_MY_BUCKET" | jq -e 'type == "object"'` before starting the app
- Fix shell quoting — single-quote the JSON: `export SST_RESOURCE_MY_BUCKET='{"BucketName":"..."}'`
- Check the linked resource's properties in sst.config.ts; only JSON-serializable plain objects can be linked
- 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
- Never hand-write SST_RESOURCE_* values; let `sst dev`/`sst deploy` inject them
- Quote JSON in single quotes when exporting env vars in shells
- Validate link payloads in sst.config.ts are plain JSON-serializable objects
- Add a CI smoke test that imports the SDK with the same env vars the runtime uses
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
- panic(err)
- expect JSON object open with '{'
- expecting JSON key should be always a string: %T: %v
- JSON value can't be decoded: %T: %v
- expect JSON object close with '}'
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/56a92e32f769c1aa.
Report an issue: GitHub.