dgraph-io/dgraph · error
UpdateExtSnapshotStreamingStateRequest must not be nil
Error message
UpdateExtSnapshotStreamingStateRequest must not be nil
What it means
UpdateExtSnapshotStreamingState is a gRPC admin operation that arms (or disarms) external-snapshot import mode — a destructive operation that replaces a group store. The server rejects a nil request pointer outright before any authorization or Raft proposal (edgraph/server.go:2058). This guards the handler against malformed gRPC calls where the request body was never populated.
Source
Thrown at edgraph/server.go:2058
if !x.WorkerConfig.AclEnabled {
return nil
}
ns, err := x.ExtractNamespaceFrom(ctx)
if err != nil {
return err
}
if tc.Hash != getHash(ns, tc.StartTs) {
return x.ErrHashMismatch
}
return nil
}
func (s *Server) UpdateExtSnapshotStreamingState(ctx context.Context,
req *api.UpdateExtSnapshotStreamingStateRequest) (v *api.UpdateExtSnapshotStreamingStateResponse, err error) {
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")
}
View on GitHub (pinned to 759e242be6)
Solutions
- Construct and pass a valid api.UpdateExtSnapshotStreamingStateRequest with Start or Finish set (exactly one of them)
- Use the official Dgraph Go client (dgo) admin APIs rather than invoking the raw gRPC method manually
- Check your proxy/interceptor layer for dropped request bodies if you believe you sent a request
- If using generated stubs, verify the field is populated before Dial/Invoke
Example fix
// before
conn.UpdateExtSnapshotStreamingState(ctx, nil)
// after
req := &api.UpdateExtSnapshotStreamingStateRequest{Start: true}
resp, err := conn.UpdateExtSnapshotStreamingState(ctx, req) Defensive patterns
Strategy: validation
Validate before calling
func validExtSnapReq(r *api.UpdateExtSnapshotStreamingStateRequest) bool {
return r != nil
}
// guard before RPC:
// if !validExtSnapReq(req) { return errors.New("request required") } Type guard
func isNonNilReq(r *api.UpdateExtSnapshotStreamingStateRequest) bool {
return r != nil
} Try / catch
resp, err := client.UpdateExtSnapshotStreamingState(ctx, req)
if err != nil && strings.Contains(err.Error(), "must not be nil") {
// client bug: construct the request and retry once
} Prevention
- Always construct the request struct before invoking admin RPCs
- Wrap raw gRPC calls in typed helpers that reject nil requests
- Prefer dgo/admin tooling over hand-rolled RPC invocations
- Add unit tests asserting admin calls receive populated requests
When it happens
Trigger: Calling the UpdateExtSnapshotStreamingState gRPC method with a nil request message — typically a hand-rolled client invoking the RPC without constructing api.UpdateExtSnapshotStreamingStateRequest, or a wrapper passing nil through.
Common situations: Custom admin scripts or generated client misuse where the request struct is omitted; middleware/proxy layers forwarding empty bodies; SDK code paths where optional request arguments default to nil.
Related errors
- UpdateExtSnapshotStreamingStateRequest cannot have both Star
- 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/503eaa6d6200565d.
Report an issue: GitHub.