{"record":{"id":"ea072cb335d5d2db","repo":"dgraph-io/dgraph","slug":"namespace-d-tablet-s-is-already-being-serve","errorCode":null,"errorMessage":"namespace: %d. Tablet: [%s] is already being served by group: [%d]","messagePattern":"namespace: (.+?)\\. Tablet: \\[(.+?)\\] is already being served by group: \\[(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"dgraph/cmd/zero/tablet.go","lineNumber":122,"sourceCode":"\t\t\tbreak\n\t\t}\n\t}\n\tif !isKnown {\n\t\treturn &pb.Status{Code: 1, Msg: x.ErrorInvalidRequest},\n\t\t\tfmt.Errorf(\"group: [%d] is not a known group\", req.DstGroup)\n\t}\n\n\ttablet := x.NamespaceAttr(req.Namespace, req.Tablet)\n\ttab := s.ServingTablet(tablet)\n\tif tab == nil {\n\t\treturn &pb.Status{Code: 1, Msg: x.ErrorInvalidRequest},\n\t\t\tfmt.Errorf(\"namespace: %d. No tablet found for: %s\", req.Namespace, req.Tablet)\n\t}\n\n\tsrcGroup := tab.GroupId\n\tif srcGroup == req.DstGroup {\n\t\treturn &pb.Status{Code: 1, Msg: x.ErrorInvalidRequest},\n\t\t\tfmt.Errorf(\"namespace: %d. Tablet: [%s] is already being served by group: [%d]\",\n\t\t\t\treq.Namespace, req.Tablet, srcGroup)\n\t}\n\n\tif err := s.movePredicate(tablet, srcGroup, req.DstGroup); err != nil {\n\t\tglog.Errorf(\"namespace: %d. While moving predicate %s from %d -> %d. Error: %v\",\n\t\t\treq.Namespace, req.Tablet, srcGroup, req.DstGroup, err)\n\t\treturn &pb.Status{Code: 1, Msg: x.Error}, err\n\t}\n\n\treturn &pb.Status{Code: 0, Msg: fmt.Sprintf(\"namespace: %d. \"+\n\t\t\"Predicate: [%s] moved from group [%d] to [%d]\", req.Namespace, req.Tablet, srcGroup,\n\t\treq.DstGroup)}, nil\n}\n\n// movePredicate is the main entry point for move predicate logic. This Zero must remain the leader\n// for the entire duration of predicate move. If this Zero stops being the leader, the final\n// proposal of reassigning the tablet to the destination would fail automatically.\nfunc (s *Server) movePredicate(predicate string, srcGroup, dstGroup uint32) (err error) {","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/dgraph/cmd/zero/tablet.go#L104-L140","documentation":"MoveTablet reads the group currently serving the tablet (tab.GroupId) and compares it to the requested destination group. If they are equal, the move is a no-op, so Zero short-circuits with an invalid-request Status rather than performing a pointless move cycle. The error is purely informational — the tablet is already in the requested state.","triggerScenarios":"Calling /moveTablet with dst_group equal to the group already serving the predicate — e.g. re-running a completed move command, or a script computing destination from the same membership snapshot used to pick the source.","commonSituations":"Idempotent re-run of an automation script after the first move succeeded; operator copied the source group into the destination field; a prior rebalancer already moved the tablet to the target group.","solutions":["No action needed — the tablet is already served by the requested group; verify with /state","If the goal was to move it elsewhere, pass a different dst_group","Make automation scripts compare tab.GroupId to dst_group and skip no-op moves"],"exampleFix":"// before\ncurl 'localhost:6080/moveTablet?tablet=name&dst_group=2'  // group 2 already serves it\n// after\nSTATE=$(curl -s localhost:6080/state)\nCUR=$(echo \"$STATE\" | jq '.groups[\"2\"].tablets.name.groupId')\n[ \"$CUR\" != 2 ] && curl 'localhost:6080/moveTablet?tablet=name&dst_group=2'","handlingStrategy":"validation","validationCode":"state=$(curl -s localhost:6080/state)\ncur=$(echo \"$state\" | jq -r --arg p \"$TABLET\" '.groups | to_entries[] | select(.value.tablets[$p]) | .key')\nif [ \"$cur\" = \"$DST_GROUP\" ]; then echo \"already in group $DST_GROUP, skipping\"; exit 0; fi","typeGuard":"move_is_noop() {\n  local cur\n  cur=$(curl -s localhost:6080/state | jq -r --arg p \"$1\" '.groups | to_entries[] | select(.value.tablets[$p]) | .key')\n  [ \"$cur\" = \"$2\" ]\n}","tryCatchPattern":"resp=$(curl -s \"localhost:6080/moveTablet?tablet=$TABLET&dst_group=$DST_GROUP\")\ncase $(echo \"$resp\" | jq -r .msg) in\n  *\"already being served\"*) echo \"no-op move, ignoring\";; *) echo \"move result: $resp\";; esac","preventionTips":["Make move scripts idempotent: read current group from /state and skip if equal","Don't reuse a stale membership snapshot to pick destination groups"],"tags":["dgraph","zero","tablet","no-op","idempotency"],"backgroundTag":"tablet-already-in-target-group","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}