{"record":{"id":"460a9cba11304d72","repo":"vitessio/vitess","slug":"not-allowed-read-only-security-policy-enforced","errorCode":null,"errorMessage":"not allowed: read-only security-policy enforced","messagePattern":"not allowed: read-only security-policy enforced","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/acl/read_only_policy.go","lineNumber":24,"sourceCode":"You may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\npackage acl\n\nimport (\n\t\"errors\"\n\t\"net/http\"\n)\n\nvar errReadOnly = errors.New(\"not allowed: read-only security-policy enforced\")\n\n// readOnlyPolicy allows DEBUGGING and MONITORING roles for everyone,\n// while denying any other roles (e.g. ADMIN) for everyone.\ntype readOnlyPolicy struct{}\n\n// CheckAccessHTTP disallows all HTTP access.\nfunc (readOnlyPolicy) CheckAccessHTTP(req *http.Request, role string) error {\n\tswitch role {\n\tcase DEBUGGING, MONITORING:\n\t\treturn nil\n\tdefault:\n\t\treturn errReadOnly\n\t}\n}\n\nfunc init() {\n\tRegisterPolicy(\"read-only\", readOnlyPolicy{})\n}","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/acl/read_only_policy.go#L6-L42","documentation":"When fetching table sizes per shard, vtadmin selects one random serving tablet from each shard to query. If a shard has no tablets in the SERVING state, the query cannot proceed and this wrapped ErrNoServingTablet error is returned for that shard.","triggerScenarios":"Calling a table-size / schema RPC that iterates shards when a shard in the keyspace has zero tablets with State == Tablet_SERVING (all replicas drained, only non-serving tablets present).","commonSituations":"A shard whose tablets are all down for maintenance; a newly created shard before tablets are started; tablets stuck in a non-serving state after a failed restart; wrong cluster selected in vtadmin config.","solutions":["Start or restore at least one serving tablet for the affected shard (vtctldclient StartTablet / restart vttablet)","Check tablet states with vtctldclient GetTablets and fix any tablets stuck non-serving","Prune truly dead shards/tablets from the topology if the shard is intentionally retired"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"serving := 0\nfor _, t := range tablets {\n\tif t.Tablet.Keyspace == ks && t.Tablet.Shard == shard && t.State == vtadminpb.Tablet_SERVING {\n\t\tserving++\n\t}\n}\nif serving == 0 { return errors.New(\"shard has no serving tablets; skip or fix before calling\") }","typeGuard":"func hasServingTablet(tablets []*vtadminpb.Tablet, ks, shard string) bool {\n\tfor _, t := range tablets {\n\t\tif t.Tablet.Keyspace == ks && t.Tablet.Shard == shard && t.State == vtadminpb.Tablet_SERVING {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}","tryCatchPattern":null,"preventionTips":["Check tablet serving states before issuing schema/size queries per shard","Keep at least one serving tablet per shard during maintenance windows","Alert on shards with zero SERVING tablets"],"tags":["vtadmin","tablets","serving","topology"],"backgroundTag":"no-serving-tablet","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}