hasura/graphql-engine · error · Error
failed to parse a number: {error:?}
Error message
failed to parse a number: {error:?} What it means
Lexer error: the bytes looked like a number but lexical_core could not parse them as a valid numeric value (the underlying lexical error is in {error}). This catches numeric syntax that survives character scanning but violates numeric grammar, such as overflow of the target type or malformed float syntax.
Source
Thrown at v3/crates/graphql/lang-graphql/src/lexer/number.rs:28
Float64(f64),
// Int32(i32),
Int64(i64),
}
impl Display for NumberToken {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
NumberToken::Float64(float) => float.fmt(f),
NumberToken::Int64(i) => i.fmt(f),
}
}
}
#[derive(Error, Debug, PartialEq, Eq, Clone)]
pub enum Error {
#[error("expected a digit, but found: {found:?}")]
DigitExpected { found: Option<u8> },
#[error("failed to parse a number: {error:?}")]
LexicalError { error: lexical_core::Error },
#[error("lookahead of a number cannot be a 'NameStart': {0:?}")]
NameStart(u8),
}
pub fn parse_number(bytes: &[u8]) -> Result<(NumberToken, usize), Error> {
let number_start = 0;
let mut ix = 0;
// Parse the optional negative sign
if let Some(&b'-') = bytes.get(ix) {
ix += 1;
}
// Count the number of integers present, until you hit a non-digit.
// This helps to distinguish between integers and floats
let integer_count = bytes[ix..]
.iter()
.take_while(|&&b| b.is_ascii_digit())
.count();View on GitHub (pinned to 724551b9ae)
Solutions
- Pass the large value as a string variable and coerce server-side, or as a variable of the proper scalar type
- Fix the malformed exponent/float syntax
- Check the lexical error variant for overflow vs syntax
Example fix
# before
query { node(id: 9007199254740993) }
# after
query($id: bigint!) { node(id: $id) } Defensive patterns
Strategy: validation
Validate before calling
// Bound inline integer literals to safe range or switch to variables if (Math.abs(value) > Number.MAX_SAFE_INTEGER) useVariable();
Type guard
const isSafeInlineNumber = (n) => Number.isFinite(n) && Math.abs(n) <= Number.MAX_SAFE_INTEGER;
Try / catch
// On lexical number errors, inspect the variant: overflow -> variable; syntax -> fix literal
Prevention
- Send big IDs as string/bigint variables
- Avoid pasted formatted numbers
When it happens
Trigger: Extremely large integer literals exceeding the representable range; malformed exponent notation like '1e+'; locale/format artifacts pasted into query text.
Common situations: Passing 64-bit IDs larger than the float/int literal limit as inline literals; copy-pasting numbers with exotic formatting.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- expected a digit, but found: {found:?}
- lookahead of a number cannot be a 'NameStart': {0:?}
- expected a \" but found: {0:?}
- string is unterminated
- unexpected character in string: {0:?}
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/fad6297eec04612e.
Report an issue: GitHub.