{"record":{"id":"90a292557a6e69cf","repo":"influxdata/influxdb","slug":"unexpected-query-error-0","errorCode":null,"errorMessage":"unexpected query error: {0}","messagePattern":"unexpected query error: (.+?)","errorType":"http","errorClass":"QueryError","httpStatus":500,"severity":"error","filePath":"core/iox_v1_query_api/src/error.rs","lineNumber":13,"sourceCode":"use std::fmt::Debug;\n\nuse datafusion::error::DataFusionError;\nuse iox_query_influxql_rewrite as rewrite;\nuse thiserror::Error;\n\n/// Error type for the v1 API\n///\n/// This is used to catch errors that occur during the streaming process.\n/// [`anyhow::Error`] is used as a catch-all because if anything fails during\n/// that process it will result in a 500 INTERNAL ERROR.\n#[derive(Debug, thiserror::Error)]\n#[error(\"unexpected query error: {0}\")]\npub struct QueryError(#[from] pub anyhow::Error);\n\n#[derive(Debug, Error)]\npub enum Error {\n    /// The requested path has no registered handler.\n    #[error(\"not found: {0}\")]\n    NoHandler(String),\n\n    #[error(\"authorization failure: {0}\")]\n    AuthorizationFailure(String),\n\n    #[error(\"invalid mime type ({0})\")]\n    InvalidMimeType(String),\n\n    /// Missing parameters for query\n    #[error(\"missing query parameters 'db' and 'q'\")]\n    MissingQueryParams,\n","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/core/iox_v1_query_api/src/error.rs#L1-L31","documentation":"`iox_v1_query_api::QueryError` is a newtype over `anyhow::Error` used as a catch-all for any failure during the v1 query streaming process. Because anything failing mid-stream must result in a 500 INTERNAL ERROR, the library wraps arbitrary errors into this type and renders them as `unexpected query error: {0}`.","triggerScenarios":"Any `?`-propagated `anyhow::Error` inside the v1 query API handlers — e.g. failures while executing the query plan, streaming result rows, or converting data — converted automatically via the `#[from] anyhow::Error` impl.","commonSituations":"A malformed InfluxQL query slips past earlier validation, storage/reader errors occur mid-response, or an internal dependency returns an error that the API layer deliberately does not classify (all become 500s).","solutions":["Inspect the chained `source()` of the inner `anyhow::Error` (print with `{:?}`) to find the root cause.","Check server logs for the full error chain; the 500 response body intentionally hides details.","Fix the underlying query/data issue that caused the internal failure (bad query, missing data, storage error)."],"exampleFix":"// before\nlet result = run_query(ctx, q)?; // surfaces as unexpected query error\n// after\nlet result = run_query(ctx, q).map_err(|e| { tracing::error!(error = ?e, \"query failed\"); QueryError(e) })?;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn is_query_error(e: &dyn std::error::Error) -> bool {\n    e.downcast_ref::<iox_v1_query_api::QueryError>().is_some()\n}","tryCatchPattern":"match api.query(sql).await {\n    Ok(rows) => use(rows),\n    Err(e) if is_query_error(e.as_ref()) => {\n        let chain: Vec<_> = e.chain().map(|c| c.to_string()).collect();\n        log::error!(\"query 500 chain: {chain:?}\");\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Validate InfluxQL syntax client-side before submission to catch most internal failures early.","Log the full anyhow error chain (`{:?}`), not just `Display`, when debugging 500s.","Retry with exponential backoff only for transient storage errors; do not blind-retry malformed queries."],"tags":["rust","http-api","internal-error","anyhow","thiserror"],"backgroundTag":"database-query-failed","analyzedSha":"06200ef96ba82c5f6727e5038a83af8e722c6875","analyzedAt":"2026-09-19T12:55:30.003Z","contentChangedAt":"2026-09-19T12:55:30.003Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}