{"record":{"id":"15bd56acc1d5018e","repo":"vitessio/vitess","slug":"error-setting-tablet-to-read-only-w","errorCode":null,"errorMessage":"Error setting tablet to read-only: %w","messagePattern":"Error setting tablet to read-only: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtadmin/api.go","lineNumber":2375,"sourceCode":"\t}, nil\n}\n\n// SetReadOnly is part of the vtadminpb.VTAdminServer interface.\nfunc (api *API) SetReadOnly(ctx context.Context, req *vtadminpb.SetReadOnlyRequest) (*vtadminpb.SetReadOnlyResponse, error) {\n\tspan, ctx := trace.NewSpan(ctx, \"API.SetReadOnly\")\n\tdefer span.Finish()\n\n\ttablet, c, err := api.getTabletForAction(ctx, span, rbac.ManageTabletWritabilityAction, req.Alias, req.ClusterIds)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\terr = c.SetWritable(ctx, &vtctldatapb.SetWritableRequest{\n\t\tTabletAlias: tablet.Tablet.Alias,\n\t\tWritable:    false,\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"Error setting tablet to read-only: %w\", err)\n\t}\n\n\treturn &vtadminpb.SetReadOnlyResponse{}, nil\n}\n\n// SetReadWrite is part of the vtadminpb.VTAdminServer interface.\nfunc (api *API) SetReadWrite(ctx context.Context, req *vtadminpb.SetReadWriteRequest) (*vtadminpb.SetReadWriteResponse, error) {\n\tspan, ctx := trace.NewSpan(ctx, \"API.SetReadWrite\")\n\tdefer span.Finish()\n\n\ttablet, c, err := api.getTabletForAction(ctx, span, rbac.ManageTabletWritabilityAction, req.Alias, req.ClusterIds)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\terr = c.SetWritable(ctx, &vtctldatapb.SetWritableRequest{\n\t\tTabletAlias: tablet.Tablet.Alias,\n\t\tWritable:    true,","sourceCodeStart":2357,"sourceCodeEnd":2393,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtadmin/api.go#L2357-L2393","documentation":"SetReadOnly calls vtctld SetWritable(writable=false) on the tablet; if that RPC fails, VTAdmin wraps the error with this message. The tablet remains in its prior writability state and the caller receives the wrapped underlying error.","triggerScenarios":"Calling API.SetReadOnly when the cluster's SetWritable RPC to vtctld fails — vtctld unreachable, tablet down, or the tablet rejects the command.","commonSituations":"Tablet already drained/in a transitional state; vtctld service down; network timeout between vtadmin and vtctld; tablet alias belongs to a retired tablet.","solutions":["Check the wrapped error for the failing tablet and verify the tablet is up (vtctld GetTablet / tablet status page)","Verify vtadmin can reach the cluster's vtctld and retry SetReadOnly","If the tablet is gone, correct the alias or remove it from use"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// confirm the tablet is reachable via topo before calling\n// e.g. tablet, err := client.GetTablet(ctx, alias); require tablet != nil and state healthy","typeGuard":null,"tryCatchPattern":"resp, err := client.SetReadOnly(ctx, req)\nif err != nil {\n    if strings.Contains(err.Error(), \"Error setting tablet to read-only\") {\n        return fmt.Errorf(\"tablet %s not set read-only: %w — check vtctld/tablet health\", alias, err)\n    }\n    return err\n}","preventionTips":["Check tablet health in the topo before issuing SetWritable calls","Ensure vtadmin has network access to each cluster's vtctld","Handle already-achieved states gracefully (tablet already read-only) to keep operations idempotent"],"tags":["vtadmin","tablet","vtctld","rpc"],"backgroundTag":"vtctld-rpc-failed","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}