{"record":{"id":"3c3579445fbe8c16","repo":"atuinsh/atuin","slug":"bug-in-list-query-please-report","errorCode":null,"errorMessage":"bug in list query. please report","messagePattern":"bug in list query\\. please report","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/atuin-client/src/database.rs","lineNumber":563,"sourceCode":"            };\n        }\n\n        if unique {\n            query.group_by(\"command\").having(\"max(timestamp)\");\n        }\n\n        if let Some(max) = max {\n            query.limit(max);\n        }\n\n        // Inclusive on both ends, matching `range()`. `stats` relies on this to count a\n        // command recorded exactly on a period boundary (e.g. at midnight).\n        if let Some((from, to)) = range {\n            query.and_where_ge(\"timestamp\", from.unix_timestamp_nanos() as i64);\n            query.and_where_le(\"timestamp\", to.unix_timestamp_nanos() as i64);\n        }\n\n        let query = query.sql().expect(\"bug in list query. please report\");\n\n        let res = sqlx::query(sqlx::AssertSqlSafe(query))\n            .map(Self::query_history)\n            .fetch_all(&self.pool)\n            .await?;\n\n        Ok(res)\n    }\n\n    async fn range(&self, from: OffsetDateTime, to: OffsetDateTime) -> Result<Vec<History>> {\n        debug!(\"listing history from {:?} to {:?}\", from, to);\n\n        let res = sqlx::query(\n            \"select * from history where timestamp >= ?1 and timestamp <= ?2 order by timestamp asc\",\n        )\n        .bind(from.unix_timestamp_nanos() as i64)\n        .bind(to.unix_timestamp_nanos() as i64)\n            .map(Self::query_history)","sourceCodeStart":545,"sourceCodeEnd":581,"githubUrl":"https://github.com/atuinsh/atuin/blob/202f6ad98ee0da165c35cdb2afbc5b13d6ab81a1/crates/atuin-client/src/database.rs#L545-L581","documentation":"A panic (std::io::Error::expect-style assertion) in Database::list when sql_builder's SqlBuilder::sql() fails to render the constructed SELECT. The builder was driven through filters (Global/Host/Session/SessionPreload/Directory/Workspace), optional group_by/having for unique, limit, and the inclusive timestamp range — and rendering still failed. sql() only errors when the builder is in an invalid state (e.g. no table, empty projection), which no combination of the public arguments can produce; the message literally asks you to report it because it indicates a bug in Atuin itself.","triggerScenarios":"Calling Database::list with any combination of filters/max/unique/range — the panic path requires a code regression, such as a filter arm forgetting select_from or adding an invalid SqlName/field. It is not reachable via user config or data.","commonSituations":"Virtually never seen in released builds; appears when developing Atuin and adding a new FilterMode or query clause that breaks the builder, or after a refactor drops a required builder step.","solutions":["If you are a user: update Atuin — this is an internal bug, not a configuration problem","Report it upstream (github.com/atuinsh/atuin issues) with the panic backtrace and the atuin version","If you are developing: bisect your changes to the query construction in list() and test each builder mutation with .sql() before chaining further","Add a unit test covering the exact filter combination that panicked"],"exampleFix":"// before (development-time cause): a filter arm forgets to keep the builder valid\nFilterMode::Global => &mut query,\n// after: ensure every arm returns the same, still-valid builder and smoke-test rendering\nlet sql = query.sql().expect(\"bug in list query. please report\");","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Panic via expect(): not catchable as a normal error. In embedding code, run the\n// query on a thread and treat a join error as 'internal bug' if you must contain it:\nlet handle = std::thread::spawn(move || db.list(&filters, &ctx, max, unique, false, None));\nmatch handle.join() {\n    Ok(Ok(rows)) => { /* use rows */ }\n    Ok(Err(e)) => { /* database error */ }\n    Err(_) => { /* panicked: internal invariant — report upstream */ }\n}","preventionTips":["Treat this panic as an upstream bug: update Atuin and report it with the backtrace","If developing: unit-test query.sql() rendering after every builder change in list()","Cover every FilterMode combination in tests before releasing changes","Never assume user data or settings can tune this away — it is a code path assertion"],"tags":["database","panic","invariant","sqlite","sql-builder","rust","atuin"],"backgroundTag":"internal-invariant-panic","analyzedSha":"202f6ad98ee0da165c35cdb2afbc5b13d6ab81a1","analyzedAt":"2026-08-16T19:30:24.731Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}