dgraph-io/dgraph · error

from/to can't be nil for shortest path

Error message

from/to can't be nil for shortest path

What it means

A shortest-path query requires both from and to arguments, each resolving to UID values. fill() inspects gq.ShortestPathArgs and errors if From or To is nil — meaning the query omitted one of them or the provided value did not resolve to a UID node.

Source

Thrown at query/query.go:738

				return err
			}
			args.MinWeight = minWeight
		} else if !ok {
			args.MinWeight = -math.MaxFloat64
		}

		if v, ok := gq.Args["maxfrontiersize"]; ok {
			maxfrontiersize, err := strconv.ParseInt(v, 0, 64)
			if err != nil {
				return err
			}
			args.MaxFrontierSize = maxfrontiersize
		} else if !ok {
			args.MaxFrontierSize = math.MaxInt64
		}

		if gq.ShortestPathArgs.From == nil || gq.ShortestPathArgs.To == nil {
			return errors.Errorf("from/to can't be nil for shortest path")
		}
		if len(gq.ShortestPathArgs.From.UID) > 0 {
			args.From = gq.ShortestPathArgs.From.UID[0]
		}
		if len(gq.ShortestPathArgs.To.UID) > 0 {
			args.To = gq.ShortestPathArgs.To.UID[0]
		}
	}

	if v, ok := gq.Args["first"]; ok {
		first, err := strconv.ParseInt(v, 0, 32)
		if err != nil {
			return err
		}
		args.Count = int(first)
	}
	return nil
}

View on GitHub (pinned to 759e242be6)

Solutions

  1. Supply both endpoints with valid hex UIDs: `shortest(from: 0x1, to: 0x2)`
  2. Resolve names to UIDs first (query for the uid by name) and use the resolved values
  3. Check that query variables actually substitute non-empty from/to values before sending

Example fix

// before
query {
  path as shortest(from: 0x1) { friend }
}
// after
query {
  path as shortest(from: 0x1, to: 0x2) { friend }
}
Defensive patterns

Strategy: validation

Validate before calling

function assertShortestEndpoints(q) {
  if (!q.from || !q.to) throw new Error('shortest requires both from and to UIDs');
  if (!/^0x[0-9a-fA-F]+$/.test(q.from) || !/^0x[0-9a-fA-F]+$/.test(q.to)) {
    throw new Error('from/to must be resolved UIDs in 0x form');
  }
}

Type guard

const hasShortestArgs = (q) => Boolean(q.shortestPathArgs && q.shortestPathArgs.from != null && q.shortestPathArgs.to != null && (q.shortestPathArgs.from.uid?.length ?? 0) > 0 && (q.shortestPathArgs.to.uid?.length ?? 0) > 0);

Try / catch

try {
  await txn.query(q);
} catch (e) {
  if (e.message.includes("from/to can't be nil")) {
    throw new Error('Resolve both endpoints to UIDs before issuing shortest');
  }
  throw e;
}

Prevention

When it happens

Trigger: Sending `shortest(from: 0x1)` without to; `shortest(to: 0x2)` without from; passing a name-string that Dgraph could not resolve to a UID so the arg remains nil; malformed JSON/RPC payload where shortest_path_args lacks from or to.

Common situations: Hand-built queries missing one endpoint; variable interpolation producing empty from/to; clients using names instead of UIDs with 0x notation in GraphQL+-; API consumers porting from engines with single-source path queries.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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