{"record":{"id":"e3af2c5fba497823","repo":"nats-io/nats-server","slug":"not-allowed-to-delete-system-account","errorCode":null,"errorMessage":"not allowed to delete system account","messagePattern":"not allowed to delete system account","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/accounts.go","lineNumber":4385,"sourceCode":"\t\tsubj = gk.Subject\n\t\tif store.deleteType == NoDelete {\n\t\t\terr = fmt.Errorf(\"delete must be enabled in server config\")\n\t\t} else if subj != gk.Issuer {\n\t\t\terr = fmt.Errorf(\"not self signed\")\n\t\t} else if _, ok := store.operator[gk.Issuer]; !ok {\n\t\t\terr = fmt.Errorf(\"not trusted\")\n\t\t} else if list, ok := gk.Data[\"accounts\"]; !ok {\n\t\t\terr = fmt.Errorf(\"malformed request\")\n\t\t} else if accIds, ok = list.([]any); !ok {\n\t\t\terr = fmt.Errorf(\"malformed request\")\n\t\t} else {\n\t\t\tfor _, entry := range accIds {\n\t\t\t\tif acc, ok := entry.(string); !ok ||\n\t\t\t\t\tacc == _EMPTY_ || !nkeys.IsValidPublicAccountKey(acc) {\n\t\t\t\t\terr = fmt.Errorf(\"malformed request\")\n\t\t\t\t\tbreak\n\t\t\t\t} else if acc == sysAccName {\n\t\t\t\t\terr = fmt.Errorf(\"not allowed to delete system account\")\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif err != nil {\n\t\trespondToUpdate(s, reply, _EMPTY_, fmt.Sprintf(\"delete accounts request by %s failed\", subj), err)\n\t\treturn\n\t}\n\terrs := []string{}\n\tpassCnt := 0\n\tfor _, acc := range accIds {\n\t\tif err := store.delete(acc.(string)); err != nil {\n\t\t\terrs = append(errs, err.Error())\n\t\t} else {\n\t\t\tpassCnt++\n\t\t}\n\t}","sourceCodeStart":4367,"sourceCodeEnd":4403,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/accounts.go#L4367-L4403","documentation":"The resolver explicitly refuses to delete the system account (acc == sysAccName) and returns 'not allowed to delete system account'. This is a deliberate safety guard protecting the SYS account that nats-server relies on for internal messaging/monitoring.","triggerScenarios":"Submitting a delete operator claim whose accounts list includes the system account's public key (the key matching the server's system account, e.g. from system_account config).","commonSituations":"Bulk cleanup scripts that 'delete all accounts' including SYS; operators trying to remove a compromised environment wholesale; scripts copying the full account list from the resolver without excluding SYS.","solutions":["Remove the system account public key from the claim's accounts list before publishing.","Filter out the key returned by the server's system_account config in your automation.","If SYS must be replaced, provision a new resolver/operator setup rather than deleting SYS."],"exampleFix":"// before\naccounts := allAccounts // includes system account key\n// after\naccounts := slices.DeleteFunc(allAccounts, func(a string) bool { return a == sysAccountPubKey })","handlingStrategy":"validation","validationCode":"sysKey := serverSystemAccountPubKey // from server config\nfor _, a := range accounts {\n    if a == sysKey {\n        return fmt.Errorf(\"refusing to delete system account %s\", a)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := pushClaim(jwt); err != nil && strings.Contains(err.Error(), \"not allowed to delete system account\") {\n    log.Fatalf(\"remove SYS account key from delete list; it is protected\")\n}","preventionTips":["Exclude the system account key in bulk-delete automation","Read the system_account key from server config rather than hardcoding","Audit delete claims before publishing"],"tags":["nats","system-account","operator-claims","safety"],"backgroundTag":"protected-system-account","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}