{"record":{"id":"bd442779c27157f8","repo":"hasura/graphql-engine","slug":"expected-a-digit-but-found-found","errorCode":null,"errorMessage":"expected a digit, but found: {found:?}","messagePattern":"expected a digit, but found: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/crates/graphql/lang-graphql/src/lexer/number.rs","lineNumber":26,"sourceCode":"pub enum NumberToken {\n    // Float32(f32),\n    Float64(f64),\n    // Int32(i32),\n    Int64(i64),\n}\n\nimpl Display for NumberToken {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match self {\n            NumberToken::Float64(float) => float.fmt(f),\n            NumberToken::Int64(i) => i.fmt(f),\n        }\n    }\n}\n\n#[derive(Error, Debug, PartialEq, Eq, Clone)]\npub enum Error {\n    #[error(\"expected a digit, but found: {found:?}\")]\n    DigitExpected { found: Option<u8> },\n    #[error(\"failed to parse a number: {error:?}\")]\n    LexicalError { error: lexical_core::Error },\n    #[error(\"lookahead of a number cannot be a 'NameStart': {0:?}\")]\n    NameStart(u8),\n}\n\npub fn parse_number(bytes: &[u8]) -> Result<(NumberToken, usize), Error> {\n    let number_start = 0;\n    let mut ix = 0;\n    // Parse the optional negative sign\n    if let Some(&b'-') = bytes.get(ix) {\n        ix += 1;\n    }\n    // Count the number of integers present, until you hit a non-digit.\n    // This helps to distinguish between integers and floats\n    let integer_count = bytes[ix..]\n        .iter()","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/v3/crates/graphql/lang-graphql/src/lexer/number.rs#L8-L44","documentation":"Lexer error: while scanning a number literal the parser expected a digit at the current position but found something else (found: Option<u8>, None means end of input). Produced by parse_number when the numeric token is malformed.","triggerScenarios":"Query text containing malformed numbers like '1.', '.e5', or a bare '-' where the integer part is missing; truncated queries cut off mid-number.","commonSituations":"Interpolating values into query strings with broken formatting; minified/truncated query payloads; template bugs dropping digits.","solutions":["Fix the number literal in the query (ensure integer and fractional parts are present)","Send numeric values as GraphQL variables instead of inline literals","Log the raw query text at the point of failure to spot truncation"],"exampleFix":"# before\nquery { songs(where: {duration: {_gt: .5}}) }\n# after\nquery($d: Int!) { songs(where: {duration: {_gt: $d}}) }","handlingStrategy":"validation","validationCode":"// Lint numeric literals in the query before sending\nconst BAD = /(?<![\\w.])(\\.\\d*|\\d+\\.)(?![\\d])/;","typeGuard":"const looksLikeCompleteNumber = (tok) => /^-?(\\d+|\\d+\\.\\d+|\\d+[eE][+-]?\\d+)$/.test(tok);","tryCatchPattern":"// Catch lex errors client-side, log the offending offset, and fix the literal","preventionTips":["Use variables for numbers","Never build numbers by string concatenation"],"tags":["graphql","lexer","number","parse-error"],"backgroundTag":"graphql-number-lex-error","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}