dgraph-io/dgraph · error

got unexpected value type

Error message

got unexpected value type

What it means

parseAsUint is the shared integer parser for removeNode's nodeId/groupId fields; it only accepts string and json.Number values and parses them with strconv.ParseUint. Any other JSON type (float64, bool, nil, object) lands in the default branch and produces this generic 'got unexpected value type' error, wrapped by callers into 'can't convert input.nodeId to uint64' etc.

Source

Thrown at graphql/admin/removeNode.go:86

	return parseAsUint(val, 64)
}

func parseAsUint32(val interface{}) (uint32, error) {
	ret, err := parseAsUint(val, 32)
	return uint32(ret), err
}

func parseAsUint(val interface{}, bitSize int) (uint64, error) {
	ret := uint64(0)
	var err error

	switch v := val.(type) {
	case string:
		ret, err = strconv.ParseUint(v, 10, bitSize)
	case json.Number:
		ret, err = strconv.ParseUint(v.String(), 10, bitSize)
	default:
		err = errors.Errorf("got unexpected value type")
	}

	return ret, err
}

View on GitHub (pinned to 759e242be6)

Solutions

  1. Send nodeId/groupId as a JSON number or numeric string: {"nodeId": "1"} or {"nodeId": 1}.
  2. Ensure the fields are present and non-null; remove them only if the schema marks them optional and you intend to omit them.
  3. If values originate from external JSON, coerce before sending: String(Math.trunc(id)) in JS or fmt.Sprintf("%d", v) in Go.
  4. Check the wrapped outer message to see which field (nodeId vs groupId) triggered it.
  5. Avoid re-parsing GraphQL variables with encoders that emit non-standard types.

Example fix

// before
{"input": {"nodeId": null}}
// after
{"input": {"nodeId": "1"}}
Defensive patterns

Strategy: type-guard

Validate before calling

function assertNodeId(v) {
  const n = typeof v === 'string' ? v : (typeof v === 'number' && Number.isInteger(v) ? String(v) : null);
  if (n === null || !/^\d+$/.test(n)) throw new Error('nodeId must be a numeric string or integer');
  return n;
}

Type guard

function isUintLike(v) {
  return (typeof v === 'string' && /^\d+$/.test(v)) ||
         (typeof v === 'number' && Number.isInteger(v) && v >= 0);
}

Try / catch

try {
  await gql(removeNodeMutation, { input: { nodeId: assertNodeId(nodeId) } });
} catch (e) {
  if (/unexpected value type|can't convert input\.(nodeId|groupId)/.test(e.message)) {
    // normalize the offending field to a numeric string and retry
  }
}

Prevention

When it happens

Trigger: Passing nodeId (or groupId) to removeNode as a JSON float/bool/null/object rather than a numeric string or json.Number; this happens when a client sends {"nodeId": null} or a nested value, or when custom middleware re-parses variables with a decoder producing float64 in a code path that skips the string/Number cases.

Common situations: Null fields from partially-built clients, IDs sourced from databases/JSON APIs as floats, or template interpolations yielding 'null' or objects. Also occurs with JS clients serializing large IDs imprecisely then falling into alternate shapes.

Related errors


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