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
- Send nodeId/groupId as a JSON number or numeric string: {"nodeId": "1"} or {"nodeId": 1}.
- Ensure the fields are present and non-null; remove them only if the schema marks them optional and you intend to omit them.
- If values originate from external JSON, coerce before sending: String(Math.trunc(id)) in JS or fmt.Sprintf("%d", v) in Go.
- Check the wrapped outer message to see which field (nodeId vs groupId) triggered it.
- 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
- Send IDs as integers or numeric strings, never null/bool/objects
- Sanitize IDs coming from external JSON APIs before sending
- Validate with a regex like /^\d+$/ client-side
- Keep IDs under uint64 range (avoid > 2^64-1)
- Check the outer wrapped message to identify which field failed
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
- can't convert input.tablet to string
- can't convert input to map
- can't convert input.what to string
- you must specify a 'destination' value
- invalid untilDate %q: %v
AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01).
Data as JSON: /api/errors/fb200015f4254941.
Report an issue: GitHub.