{"record":{"id":"964c61b3cffd2b07","repo":"anomalyco/sst","slug":"errprotectedstage","errorCode":"ErrProtectedStage","errorMessage":"cannot remove protected stage","messagePattern":"cannot remove protected stage","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/project/stack.go","lineNumber":120,"sourceCode":"\ntype StackCommandEvent struct {\n\tApp     string\n\tStage   string\n\tConfig  string\n\tCommand string\n\tVersion string\n}\n\ntype Error struct {\n\tMessage string   `json:\"message\"`\n\tURN     string   `json:\"urn\"`\n\tHelp    []string `json:\"help\"`\n}\n\nvar ErrStackRunFailed = fmt.Errorf(\"stack run had errors\")\nvar ErrStageNotFound = fmt.Errorf(\"stage not found\")\nvar ErrPassphraseInvalid = fmt.Errorf(\"passphrase invalid\")\nvar ErrProtectedStage = fmt.Errorf(\"cannot remove protected stage\")\nvar ErrProtectedDevStage = fmt.Errorf(\"cannot run sst dev on protected stage\")\nvar ErrPolicyViolation = fmt.Errorf(\"policy violations detected\")\nvar ErrPolicyConfigError = fmt.Errorf(\"policy configuration error\")\n\nfunc (p *Project) ResolvePolicyPackPath(policyPath string) (string, error) {\n\tvar resolvedPath string\n\tif filepath.IsAbs(policyPath) {\n\t\tresolvedPath = policyPath\n\t} else {\n\t\tresolvedPath = filepath.Join(p.PathRoot(), policyPath)\n\t}\n\n\tif _, err := os.Stat(resolvedPath); err != nil {\n\t\treturn \"\", fmt.Errorf(\"Policy pack not found in path: %v\", resolvedPath)\n\t}\n\n\treturn resolvedPath, nil\n}","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/pkg/project/stack.go#L102-L138","documentation":"ErrProtectedStage is thrown when an 'sst remove' is attempted against a stage marked as protected. Protection is enabled by setting the `protect` flag on the SST App (e.g. `export const app = new sst.SstConfig({ app: { ..., protect: true } })`). SST refuses the remove so production/staging stages are not accidentally destroyed.","triggerScenarios":"Calling Project.Run (pkg/project/run.go:39) with input.Command == \"remove\" while p.app.Protect is true — i.e. `sst remove` or `sst remove --stage <name>` on a stage whose sst.config.ts sets protect: true.","commonSituations":"CI/CD cleanup jobs running `sst remove` on a prod stage that has protect enabled; developers trying to tear down a shared production stage locally; a teammate enabled protect on the stage and the old teardown script no longer works.","solutions":["If removal is truly intended, temporarily set protect: false in sst.config.ts for that stage, deploy/re-read config, run `sst remove`, then re-enable protect.","Use `sst remove --stage <non-protected-stage>` instead of targeting the protected stage.","Instead of removing, remove individual resources via your cloud provider console/CLI when only some resources need deletion.","If protect was enabled by mistake (e.g. copied config from production), remove the `protect: true` flag from the App config."],"exampleFix":"// before (sst.config.ts)\nexport const app = new sst.SstConfig({\n  app: { name: \"myapp\", stage: \"prod\", protect: true },\n});\n// after — temporarily allow removal\nexport const app = new sst.SstConfig({\n  app: { name: \"myapp\", stage: \"prod\", protect: false },\n});","handlingStrategy":"validation","validationCode":"import { Config } from \"./sst.config\";\n// Before running remove, check the stage's protect flag\nif (app.protect && process.argv.includes(\"remove\")) {\n  throw new Error(`Stage '${app.stage}' is protected; refusing to remove.`);\n}\n// Or inspect via CLI first:\n// sst diff --stage <stage>  &&  grep -n 'protect' sst.config.ts","typeGuard":"function isProtectedStage(app: { protect?: boolean; stage: string }) {\n  return app.protect === true; // narrow to a protected-stage shape before destructive ops\n}","tryCatchPattern":null,"preventionTips":["Never hardcode production stage names in teardown scripts; always pass --stage explicitly and assert it is not in a protected list.","Keep a PROTECTED_STAGES constant checked by CI before any remove step.","Gate `sst remove` behind an explicit confirmation/CI approval workflow.","Use per-developer personal stages for experiments and keep protect enabled on shared stages."],"tags":["sst","protected-stage","infrastructure","destructive-command"],"backgroundTag":"protected-stage-deletion-blocked","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}