dgraph-io/dgraph · error
UpdateExtSnapshotStreamingStateRequest cannot have both Star
Error message
UpdateExtSnapshotStreamingStateRequest cannot have both Start and Finish set to true
What it means
The UpdateExtSnapshotStreamingState request uses Start and Finish as mutually exclusive state-transition flags: Start arms external-snapshot import/drain mode, Finish ends it. Setting both to true is contradictory, so the server rejects it after auth checks (edgraph/server.go:2074). Only one flag may be set per call — issue two sequential calls to arm and then finish.
Source
Thrown at edgraph/server.go:2074
if req == nil {
return nil, errors.New("UpdateExtSnapshotStreamingStateRequest must not be nil")
}
// External-snapshot import is a destructive admin operation: it arms import mode and
// (via StreamExtSnapshot) replaces a group store. Gate it on both authorization paths so
// it is protected under ACL and under an --security auth-token. Each gate fails open when
// its feature is unconfigured, so the arming requirement on the stream path backstops the
// bare-OSS case.
if err := AuthorizeGuardians(ctx); err != nil {
return nil, err
}
if err := hasPoormansAuth(ctx); err != nil {
return nil, err
}
if req.Start && req.Finish {
return nil, errors.New("UpdateExtSnapshotStreamingStateRequest cannot have both Start and Finish set to true")
}
groups, err := worker.ProposeDrain(ctx, req)
if err != nil {
glog.Errorf("[import] failed to propose drain mode: %v", err)
return nil, err
}
resp := &api.UpdateExtSnapshotStreamingStateResponse{Groups: groups}
return resp, nil
}
func (s *Server) StreamExtSnapshot(stream api.Dgraph_StreamExtSnapshotServer) error {
defer x.ExtSnapshotStreamingState(false)
// Authorize at stream start, before any data is consumed. Stream auth metadata rides on the
// stream's context, so the same gates used for the unary entry point apply here.View on GitHub (pinned to 759e242be6)
Solutions
- Send Start=true (Finish unset) to begin snapshot streaming, then a separate call with Finish=true (Start unset) to end it
- Add client-side validation that exactly one of Start/Finish is true before invoking the RPC
- If a struct is reused, explicitly reset the opposite flag each call
- Check for SDK/tooling updates if your client builds requests with both flags by default
Example fix
// before
req := &api.UpdateExtSnapshotStreamingStateRequest{Start: true, Finish: true}
// after
req := &api.UpdateExtSnapshotStreamingStateRequest{Start: true}
// ... later, to finish:
finishReq := &api.UpdateExtSnapshotStreamingStateRequest{Finish: true} Defensive patterns
Strategy: validation
Validate before calling
func validExtSnapFlags(r *api.UpdateExtSnapshotStreamingStateRequest) bool {
return r != nil && (r.Start != r.Finish) // exactly one set
}
// guard before RPC:
// if !validExtSnapFlags(req) { return errors.New("set exactly one of Start/Finish") } Type guard
func isExclusiveStartFinish(r *api.UpdateExtSnapshotStreamingStateRequest) bool {
return r != nil && r.Start != r.Finish
} Try / catch
resp, err := client.UpdateExtSnapshotStreamingState(ctx, req)
if err != nil && strings.Contains(err.Error(), "both Start and Finish") {
// fix request flags: send separate Start and Finish calls
} Prevention
- Issue Start and Finish as two separate RPC calls
- Validate exactly-one-flag-set before sending admin requests
- Reset opposite flags when reusing request structs
- Model the lifecycle as a state machine (idle -> started -> finished) in tooling
When it happens
Trigger: Calling UpdateExtSnapshotStreamingState with both req.Start=true and req.Finish=true in the same message — e.g. a client reusing a populated struct and flipping both fields, or constructing the request from ambiguous user input.
Common situations: Admin tooling with checkbox UIs that allow selecting both actions; retry logic that sets Finish on a request originally built for Start; clients built against different API versions where flag semantics changed.
Related errors
- UpdateExtSnapshotStreamingStateRequest must not be nil
- NQuad failed sanity check. Subject: %q, Predicate: %q, Objec
- empty variable name in function call
- empty facetKeys not allowed
- connection string cannot be empty
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/d8a1008c4b40cbf9.
Report an issue: GitHub.