anomalyco/sst · error
ErrProtectedStage
ErrProtectedStage
Error message
cannot remove protected stage
What it means
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.
Source
Thrown at pkg/project/stack.go:120
type StackCommandEvent struct {
App string
Stage string
Config string
Command string
Version string
}
type Error struct {
Message string `json:"message"`
URN string `json:"urn"`
Help []string `json:"help"`
}
var ErrStackRunFailed = fmt.Errorf("stack run had errors")
var ErrStageNotFound = fmt.Errorf("stage not found")
var ErrPassphraseInvalid = fmt.Errorf("passphrase invalid")
var ErrProtectedStage = fmt.Errorf("cannot remove protected stage")
var ErrProtectedDevStage = fmt.Errorf("cannot run sst dev on protected stage")
var ErrPolicyViolation = fmt.Errorf("policy violations detected")
var ErrPolicyConfigError = fmt.Errorf("policy configuration error")
func (p *Project) ResolvePolicyPackPath(policyPath string) (string, error) {
var resolvedPath string
if filepath.IsAbs(policyPath) {
resolvedPath = policyPath
} else {
resolvedPath = filepath.Join(p.PathRoot(), policyPath)
}
if _, err := os.Stat(resolvedPath); err != nil {
return "", fmt.Errorf("Policy pack not found in path: %v", resolvedPath)
}
return resolvedPath, nil
}View on GitHub (pinned to a0bd20f762)
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.
Example fix
// before (sst.config.ts)
export const app = new sst.SstConfig({
app: { name: "myapp", stage: "prod", protect: true },
});
// after — temporarily allow removal
export const app = new sst.SstConfig({
app: { name: "myapp", stage: "prod", protect: false },
}); Defensive patterns
Strategy: validation
Validate before calling
import { Config } from "./sst.config";
// Before running remove, check the stage's protect flag
if (app.protect && process.argv.includes("remove")) {
throw new Error(`Stage '${app.stage}' is protected; refusing to remove.`);
}
// Or inspect via CLI first:
// sst diff --stage <stage> && grep -n 'protect' sst.config.ts Type guard
function isProtectedStage(app: { protect?: boolean; stage: string }) {
return app.protect === true; // narrow to a protected-stage shape before destructive ops
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- ErrProtectedDevStage
- ErrPolicyViolation
- Invalid function definition for the "${name}" Function
- The provided ARN "${arn}" is not a Lambda function ARN.
- The provided ARN "${arn}" is not an S3 bucket ARN.
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/964c61b3cffd2b07.
Report an issue: GitHub.