hasura/graphql-engine · error · Error
string is unterminated
Error message
string is unterminated
What it means
String lexer error: a string literal was never terminated. Beyond a missing closing quote, ending a string inside a Unicode escape sequence or including a raw line break also triggers it, since GraphQL strings cannot span lines.
Source
Thrown at v3/crates/graphql/lang-graphql/src/lexer/string.rs:15
use std::cmp::min;
use std::str::from_utf8_unchecked;
use thiserror::Error;
#[derive(Error, Debug, PartialEq, Eq, Clone)]
pub enum Error {
#[error("expected a \" but found: {0:?}")]
StartingSequenceNotFound(Option<u8>),
/// An unterminated string literal was found
///
/// Apart from forgetting the ending `"`, terminating a string within a
/// Unicode escape sequence or having a line break in the string also
/// causes this error.
#[error("string is unterminated")]
Unterminated,
/// An unknown character in a string literal was found
///
/// This occurs when an invalid source character is found in a string
/// literal, such as ASCII control characters.
#[error("unexpected character in string: {0:?}")]
UnknownCharacterInString(char),
/// An unknown escape sequence in a string literal was found
///
/// Only a limited set of escape sequences are supported, this is emitted
/// when e.g. `"\l"` is parsed.
#[error("unknown escape sequence in string: {0:?}")]
UnknownEscapeSequence(String),
/// An invalid unicode escape sequence in a string literal was found, and
/// an error message is provided.View on GitHub (pinned to 724551b9ae)
Solutions
- Close the string literal, escaping any embedded quotes or newlines
- Pass multiline text as a variable instead of an inline literal
- Verify the request body is fully transmitted (not truncated)
Example fix
# before
query { songs(where: {title: {_eq: "hey}}) }
# after
query($t: String!) { songs(where: {title: {_eq: $t}}) } Defensive patterns
Strategy: validation
Validate before calling
// Client-side parse catches unterminated strings before sending
import { parse } from 'graphql';
try { parse(queryText); } catch (e) { fixQuery(e); } Type guard
const isTerminatedString = (s) => (s.match(/"/g) ?? []).length % 2 === 0;
Try / catch
// Catch the lexer error, use its offset to locate the string, close or escape it
Prevention
- Escape embedded quotes/newlines or use variables
- Verify request bodies aren't truncated by proxies
When it happens
Trigger: Forgetting the closing '"'; a literal newline pasted inside a quoted string; a truncated query that ends mid-string; an unterminated \u escape.
Common situations: Multiline text pasted into an inline string argument; client template bugs; network truncation mid-request.
Related errors
- expected a \" but found: {0:?}
- expected a digit, but found: {found:?}
- failed to parse a number: {error:?}
- lookahead of a number cannot be a 'NameStart': {0:?}
- unexpected character in string: {0:?}
AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28).
Data as JSON: /api/errors/f242e13a04f44094.
Report an issue: GitHub.