dgraph-io/dgraph · error

invalid task ID: %#x

Error message

invalid task ID: %#x

What it means

TaskStatusOverNetwork validates the task ID from a TaskStatusRequest before decoding it; an ID of 0 cannot encode a Raft ID in its upper 32 bits (taskId >> 32), so it is rejected with 'invalid task ID: %#x'. This is an input-validation error indicating the client passed an uninitialized or malformed task ID.

Source

Thrown at worker/queue.go:35

	"github.com/golang/glog"
	"github.com/pkg/errors"

	"github.com/dgraph-io/dgraph/v25/conn"
	"github.com/dgraph-io/dgraph/v25/protos/pb"
	"github.com/dgraph-io/dgraph/v25/raftwal"
	"github.com/dgraph-io/dgraph/v25/x"
	"github.com/dgraph-io/ristretto/v2/z"
)

// TaskStatusOverNetwork fetches the status of a task over the network. Alphas only know about the
// tasks created by them, but this function would fetch the task from the correct Alpha.
func TaskStatusOverNetwork(ctx context.Context, req *pb.TaskStatusRequest,
) (*pb.TaskStatusResponse, error) {
	// Extract Raft ID from Task ID.
	taskId := req.GetTaskId()
	if taskId == 0 {
		return nil, fmt.Errorf("invalid task ID: %#x", taskId)
	}
	raftId := taskId >> 32

	// Skip the network call if the required Alpha is me.
	myRaftId := State.WALstore.Uint(raftwal.RaftId)
	if raftId == myRaftId {
		worker := (*grpcWorker)(nil)
		return worker.TaskStatus(ctx, req)
	}

	// Find the Alpha with the required Raft ID.
	var addr string
	for _, group := range groups().state.GetGroups() {
		for _, member := range group.GetMembers() {
			if member.GetId() == raftId {
				addr = member.GetAddr()
			}
		}

View on GitHub (pinned to 759e242be6)

Solutions

  1. Check the error returned by Enqueue/initial mutation before using the returned task ID (error and ID can both be zero)
  2. Only build a TaskStatusRequest with a nonzero task ID obtained from a successful Enqueue
  3. If the original task ID was lost, re-run the backup/export operation to get a new one

Example fix

// before
resp, _ := pb.TaskStatusOverNetwork(ctx, &pb.TaskStatusRequest{TaskId: id})
// after
if id == 0 {
    return fmt.Errorf("no task ID recorded from mutation")
}
resp, err := pb.TaskStatusOverNetwork(ctx, &pb.TaskStatusRequest{TaskId: id})
if err != nil { return err }
Defensive patterns

Strategy: validation

Validate before calling

func validTaskID(id uint64) bool { return id != 0 }
// call: if !validTaskID(req.GetTaskId()) { return error }

Type guard

func hasTaskID(req *pb.TaskStatusRequest) bool {
    return req != nil && req.GetTaskId() != 0
}

Try / catch

meta, err := worker.TaskStatusOverNetwork(ctx, req)
if err != nil && strings.Contains(err.Error(), "invalid task ID") {
    return fmt.Errorf("no task ID recorded; capture the ID returned by a successful enqueue")
}

Prevention

When it happens

Trigger: Calling TaskStatusOverNetwork (e.g. via the resolveTask path, often while retrying a mutation that returned a task ID) with req.GetTaskId() == 0 — typically when the original mutation response was never populated with a task ID.

Common situations: A client stores the task ID before the mutation RPC returns and the field defaults to zero; retry logic constructs a TaskStatusRequest from an empty protobuf; code that ignores the error from Enqueue and uses the 0 ID returned alongside it.

Related errors


AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01). Data as JSON: /api/errors/4f67101a66abae52. Report an issue: GitHub.