{"record":{"id":"dd2000f58db6d3a1","repo":"linera-io/linera-protocol","slug":"expected-whitespace-after-query-keyword","errorCode":null,"errorMessage":"expected whitespace after 'query' keyword","messagePattern":"expected whitespace after 'query' keyword","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"linera-service/src/query_subscription.rs","lineNumber":35,"sourceCode":"use tracing::{debug, warn};\n\n/// A named GraphQL query string registered at startup via `--allow-subscription`.\n#[derive(Clone, Debug)]\npub struct RegisteredQuery {\n    /// The operation name used to refer to the query.\n    pub name: String,\n    /// The full GraphQL query string.\n    pub query: String,\n}\n\n/// Parses a GraphQL query string like `query Name { ... }` and extracts the operation name.\npub fn parse_allowed_subscription(s: &str) -> anyhow::Result<RegisteredQuery> {\n    let trimmed = s.trim();\n    let rest = trimmed\n        .strip_prefix(\"query\")\n        .ok_or_else(|| anyhow::anyhow!(\"expected query to start with 'query', got: {s}\"))?;\n    // The character right after \"query\" must be whitespace (not part of a longer word).\n    anyhow::ensure!(\n        rest.starts_with(char::is_whitespace),\n        \"expected whitespace after 'query' keyword\"\n    );\n    let rest = rest.trim_start();\n    // Extract the operation name: sequence of alphanumeric/underscore chars.\n    let name = rest\n        .split(|c: char| !c.is_alphanumeric() && c != '_')\n        .next()\n        .unwrap_or_default();\n    anyhow::ensure!(\n        !name.is_empty(),\n        \"expected an operation name after 'query', e.g. 'query MyQuery {{ ... }}'\"\n    );\n    Ok(RegisteredQuery {\n        name: name.to_string(),\n        query: trimmed.to_string(),\n    })\n}","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-service/src/query_subscription.rs#L17-L53","documentation":"parse_allowed_subscription in linera-service parses each --allow-subscription CLI value into a RegisteredQuery. It requires the trimmed string to start with the literal keyword 'query' followed by at least one whitespace character, so the keyword can be told apart from the operation name that follows. This error means the input did begin with 'query' but the next character was not whitespace, e.g. 'query{' or 'queryName'.","triggerScenarios":"Starting the linera-service node with a --allow-subscription value such as 'query{ transfers { id } }' (no space before the brace) or 'queryTransfers { ... }' (name glued to the keyword). The parse runs at startup from run(), so the process fails before any chain or network activity.","commonSituations":"Shell quoting that collapses or drops whitespace; copy-pasting a minified GraphQL query; writing an anonymous operation without a space; muscle memory from other GraphQL clients that accept 'query{...}'.","solutions":["Put whitespace between the keyword and the rest: use 'query MyQuery { ... }'","If you wrote an anonymous operation like 'query { ... }', add an operation name — this parser requires one (see the sibling error for missing names)","Quote the whole argument in the shell so whitespace survives: --allow-subscription 'query MyQuery { field }'","Check for invisible characters (e.g. a BOM or non-breaking space) pasted from docs or chat, which do count as whitespace but may surprise you; use a plain ASCII space"],"exampleFix":"# before\n--allow-subscription 'query{ transfers { id } }'\n# after\n--allow-subscription 'query Transfers { transfers { id } }'","handlingStrategy":"validation","validationCode":"// Rust: reject bad --allow-subscription values before startup\nfn starts_with_query_keyword(s: &str) -> bool {\n    let t = s.trim();\n    match t.strip_prefix(\"query\") {\n        Some(rest) => rest.starts_with(char::is_whitespace),\n        None => false,\n    }\n}\n\nfor sub in &allowed_subscriptions {\n    if !starts_with_query_keyword(sub) {\n        return Err(config_error(format!(\"bad --allow-subscription: {sub}\")));\n    }\n}","typeGuard":"fn is_wellformed_subscription(s: &str) -> bool {\n    let t = s.trim();\n    t.strip_prefix(\"query\").is_some_and(|r| r.starts_with(char::is_whitespace))\n}","tryCatchPattern":"match parse_allowed_subscription(&arg) {\n    Ok(registered) => registry.push(registered),\n    Err(e) => {\n        eprintln!(\"invalid --allow-subscription value {arg:?}: {e:#}\");\n        std::process::exit(2);\n    }\n}","preventionTips":["Always quote the whole GraphQL string in shell commands so whitespace survives","Add a startup config lint that runs starts_with_query_keyword over all subscription flags before the node boots","Prefer named operations everywhere: 'query Name { ... }' satisfies both this check and the name check"],"tags":["linera","graphql","cli","parsing","subscription"],"backgroundTag":"graphql-syntax-error","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}