Diesel Async Pagination Triggers Lifetime Error in async-graphql #[Object] Resolver
โ Rust ๐ 2025-07-18 ๐ค surdeus ๐๏ธ 17Hey all! Iโm encountering a confusing lifetime issue in a project using diesel_async, a custom pagination trait, and async-graphql.
The error doesnโt occur when I write the query inline, but does occur when I move the query into a build_query() function, even though I try to give it a 'static lifetime.
My custom pagination trait comes from this article: https://rymc.io/blog/2024/pagination-in-diesel-async/
What works (inline)
let (items, total) = users::table
.left_join(...)
.select(...)
.paginate(page)
.per_page(per_page)
.load_and_count_pages::<MyModel>(&mut conn)
.await?;
This works and compiles fine.
What fails (via function)
fn build_query(...) -> IntoBoxed<'static, _, Pg> {
users::table
.left_join(...)
.into_boxed()
}
let query = build_query(...);
let (items, total) = query
.paginate(page)
.per_page(per_page)
.load_and_count_pages::<MyModel>(&mut conn)
.await?;
This causes a lifetime error, but the error doesnโt appear at the call site โ instead, it surfaces at the #[Object] macro from async-graphql:
error[E0477]: the type `Paginated<BoxedSelectStatement<'_, ...>>` does not fulfill the required lifetime
--> src/http/handlers/my_handler.rs:23:1
|
23 | #[Object]
| ^^^^^^^^^
What Iโve tried
- Made all input arguments owned (no references)
- Explicitly set the return type of
build_query()toBoxedSelectStatement<'static, _, _, Pg, _>
What Iโd love help with
- Why does returning a boxed query from a function break
.paginate().awaitin a#[Object]resolver? - How can I structure the query builder so I can paginate it asynchronously inside
#[Object]? - Are there any best practices to avoid these lifetime traps when using Diesel + async + GraphQL?
Context
Rust version:
rustc 1.85.1 (4eb161250 2025-03-15)
Dependencies:
axum = { version = "0.8.1", features = ["multipart"] }
deadpool-diesel = { version = "0.6.1", features = ["postgres", "tracing"] }
diesel = { version = "2.2.8", features = ["chrono", "postgres", "serde_json"] }
diesel-async = { version = "0.5.2", features = ["deadpool", "postgres"] }
...
Any suggestions โ even hacky workarounds โ would be greatly appreciated! ![]()
Sorry if this is a noob question โ Iโm still new to Rust and still wrapping my head around lifetimes ![]()
I truly appreciate any pointers or explanations, even if they seem basic!
1 post - 1 participant
๐ท๏ธ rust_feed