dgraph-io/dgraph · error
failed to send request for group ID [%v] to the server: %w
Error message
failed to send request for group ID [%v] to the server: %w
What it means
Returned when out.Send of the first StreamExtSnapshotRequest (carrying only the GroupId) fails on the open stream. The server expects the group ID as the first message; a send failure means the stream is broken before any data flows.
Source
Thrown at dgraph/cmd/dgraphimport/import_client.go:196
// Open the BadgerDB instance at the specified directory
opt := badger.DefaultOptions(pdir)
opt.ReadOnly = true
ps, err := badger.OpenManaged(opt)
if err != nil {
glog.Errorf("failed to open BadgerDB at [%s]: %v", pdir, err)
return fmt.Errorf("failed to open BadgerDB at [%v]: %v", pdir, err)
}
defer func() {
if err := ps.Close(); err != nil {
glog.Warningf("[import] Error closing BadgerDB: %v", err)
}
}()
// Send group ID as the first message in the stream
glog.Infof("[import] Sending request for streaming external snapshot for group ID [%v]", groupId)
groupReq := &api.StreamExtSnapshotRequest{GroupId: groupId}
if err := out.Send(groupReq); err != nil {
return fmt.Errorf("failed to send request for group ID [%v] to the server: %w", groupId, err)
}
if _, err := out.Recv(); err != nil {
return fmt.Errorf("failed to receive response for group ID [%v] from the server: %w", groupId, err)
}
glog.Infof("[import] Group [%v]: Received ACK for sending group request", groupId)
// Configure and start the BadgerDB stream
glog.Infof("[import] Starting BadgerDB stream for group [%v]", groupId)
if err := streamBadger(ctx, ps, out, groupId); err != nil {
return fmt.Errorf("badger streaming failed for group [%v]: %v", groupId, err)
}
return nil
}
// streamBadger runs a BadgerDB stream to send key-value pairs to the specified group.
// It creates a new stream at the maximum sequence number and sends the data to the specified group.
// It also sends a final 'done' signal to mark completion.View on GitHub (pinned to 759e242be6)
Solutions
- Check the wrapped gRPC error/status for the root cause (Unavailable, Canceled, Internal).
- Confirm the group ID exists in the current cluster (dgraph status / raft state).
- Disable LB idle-timeout killing of long gRPC streams or add keepalive settings.
- Retry the whole streamSnapshotForGroup; streams are not resumable.
- Verify the Alpha is healthy and not restarting during the import.
Example fix
// before
if err := out.Send(groupReq); err != nil {
return fmt.Errorf("failed to send request for group ID [%v] to the server: %w", groupId, err)
}
// after
if err := out.Send(groupReq); err != nil {
if errors.Is(err, io.EOF) {
return fmt.Errorf("server closed stream for group %d before handshake; check server logs and group membership", groupId)
}
return fmt.Errorf("failed to send request for group ID [%v] to the server: %w", groupId, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
if ctx.Err() != nil {
return fmt.Errorf("context already cancelled before stream handshake: %w", ctx.Err())
} Type guard
func isEOFOrBrokenStream(err error) bool {
return errors.Is(err, io.EOF) ||
(errors.Is(err, context.Canceled)) ||
(func() bool { s, ok := status.FromError(err); return ok && s.Code() == codes.Unavailable }())
} Try / catch
if err := out.Send(groupReq); err != nil {
if isEOFOrBrokenStream(err) {
// stream died before handshake: rebuild stream and retry once
return retryStreamSnapshotForGroup(ctx, dc, pdir, groupId)
}
return fmt.Errorf("failed to send request for group ID [%v] to the server: %w", groupId, err)
} Prevention
- Add gRPC keepalive so idle streams are not reaped by LBs.
- Avoid proxies between importer and Alpha for long streams.
- Validate group IDs against current cluster membership before import.
- Don't cancel the context between stream open and the first send.
When it happens
Trigger: The gRPC stream was closed by the server right after setup (server-side error, load balancer idle timeout, Alpha crash); context cancelled mid-send; sending on a stream the server already rejected (e.g. unknown group).
Common situations: Long-lived stream killed by an intermediate proxy/LB idle timeout; Alpha draining or restarting between stream open and first send; cluster reconfiguration changed group membership so the group ID is rejected.
Related errors
- failed to start external snapshot stream for group %d: %w
- failed to receive response for group ID [%v] from the server
- failed to send data chunk: %w
- failed to send 'done' signal for group [%d]: %w
- failed to disable drain mode: %v
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/3b4b104d77941ff1.
Report an issue: GitHub.