Skip to main content

Results

A reader never gets a bag of booleans. It gets a sealed value: a QueryResult<T> for a query, a MutationResult<TData, TVariables> for a mutation, a CombinedResult<T> for several queries read together. A switch over one is exhaustive, and each case carries exactly the fields that exist in it. This page lists every field and getter and which case carries it. A TanStack Query name is given only where it differs from the Dart one, and a member with no counterpart there says so.

Where a result comes from — an observer's currentResult, a controller's value, a builder's argument — is on widgets and controllers and caches and observers. For where the two libraries behave differently, see differences from TanStack Query.

QueryResult​

QueryResult<TData> is what every query observer hands out, and a new one whenever something it reports changes. It is sealed, with three cases:

CaseWhen
QueryPendingNothing has resolved: no data, no error. The first load; a query without data fetching again after a failure; a query after a reset; a disabled query that has never fetched (then fetchStatus is idle).
QuerySuccessThe query holds data: fetched, seeded with initialData, written with setQueryData, or a placeholder. May be fetching at the same time — a background refresh.
QueryErrorThe last fetch failed after its retries, or the observer's select threw. Data from an earlier success stays in staleData.

What the query holds is the case. What it is doing is fetchStatus and the flags derived from it, which vary independently of the case. See queries for how the two axes combine.

Fields and getters​

"All" means the field is declared on QueryResult and every case carries it.

NameTypeOn which casesMeaning
statusQueryStatusallThe case, as an enum: pending, success or error. For storing or comparing rather than matching.
fetchStatusFetchStatusallWhat the query is doing: fetching, paused or idle.
isPendingboolallThis is a QueryPending.
isSuccessboolallThis is a QuerySuccess, whether or not a refresh is running.
isErrorboolallThis is a QueryError.
isFetchingboolallfetchStatus is fetching: a first load or a refetch is in flight.
isPausedboolallfetchStatus is paused: a fetch wants to run but waits for the network (per networkMode) or for the app to return to the foreground before its next retry.
isLoadingboolallPending and fetching: the first load. False for a pending query that is not fetching, such as a disabled one.
isRefetchingboolallFetching and not pending: a background refresh of data on screen, including data still held after a failed refetch. A query without data that fetches again is pending, so this is false.
dataOrNullTData?alldata on a success, staleData on an error, null when pending. TanStack: data.
errorOrNullObject?allerror on a QueryError, null otherwise. TanStack: error.
dataTDataQuerySuccessThe data, after select when the observer has one. A placeholder when isPlaceholderData is true.
errorObjectQueryErrorWhat the last attempt of the failed fetch threw, or what select threw. A cancelled fetch that was not reverted fails with a CancelledError.
stackTraceStackTraceQueryErrorWhere error was thrown. No TanStack counterpart.
staleDataTData?QueryErrorThe data from the last successful fetch or write, kept through the error; null when there was none. TanStack: data, in the error state.
hasStaleDataboolQueryErrorWhether staleData means anything. Tells a real null from none when TData is nullable. No TanStack counterpart.
isLoadingErrorboolQueryErrorThe first load failed; there is nothing to show (!hasStaleData).
isRefetchErrorboolQueryErrorA refetch failed over data that is still on screen (hasStaleData).
dataUpdatedAtDateTime?allWhen the data was last written, by a fetch or by hand — what staleTime counts from. null until something has been.
errorUpdatedAtDateTime?allWhen the query last ended in an error (or select last threw). Not cleared by a later success.
failureCountintallFailed attempts within the current fetch. Reset when a new fetch starts.
failureReasonObject?allWhat the latest failed attempt threw. Kept while retries continue and after the fetch finally fails; cleared when the next fetch starts or an attempt succeeds.
failureStackTraceStackTrace?allThe stack trace of failureReason; null whenever it is. No TanStack counterpart.
errorUpdateCountintallHow many times the query has ended in an error over its whole life. Never goes down.
consecutiveErrorCountintallFetches in a row that ended in an error. Back to zero with the next fetched data; a manual write and a cancelled fetch leave it alone. See polling. No TanStack counterpart.
isStaleboolallThe data is older than this observer's staleTime, or was invalidated. A query with no data is stale; a disabled one never is. StaleTime.static data is never stale, invalidated or not.
isEnabledboolallThis observer's enabled currently lets the query fetch on its own. refetch runs regardless.
isFetchedboolallAnything has ever been fetched or written, successfully or not.
isFetchedAfterMountboolallA fetch or write has completed since this observer attached, as opposed to data already in the cache.
isPlaceholderDataboolall (true only on QuerySuccess)data is the observer's placeholderData, not cached data. See placeholder data.
refetchQueryRefetch<TData>allrefetch({bool cancelRefetch = true}): fetches again regardless of enabled and staleTime, and completes with the result that follows — never with an error. cancelRefetch: true cancels a fetch in flight on a query that holds data and starts over; a first load is joined. false joins the fetch in flight.

TanStack Query's isInitialLoading (a deprecated alias of isLoading) and promise have no counterpart.

A throwing select

When the observer's select throws, the result is a QueryError carrying what it threw, with the last value select produced, if any, kept in staleData. The cached data is untouched, and the next successful selection clears the error.

Equality​

Results compare by value. Two results are equal when they are the same case and carry equal data, error and fields; refetch and the stack traces take no part. An unchanged result therefore compares equal to the previous one, which is what a buildWhen or a ValueListenable relies on.

QueryStatus and FetchStatus​

QueryStatus is what the query holds; FetchStatus is what it is doing. Any status combines with any fetch status.

EnumValueMeaning
QueryStatuspendingNo data and no error: before the first fetch settles (unless initialData seeded the query), after a reset, and while a query without data fetches again after a failure.
QueryStatussuccessThe query holds data, fetched or seeded.
QueryStatuserrorThe last fetch failed and its retries are spent. Data from an earlier success is kept alongside.
FetchStatusfetchingA fetch is in flight.
FetchStatuspausedA fetch wants to run but cannot: offline under a networkMode that waits, or a retry waiting for the app to return to the foreground. See network mode.
FetchStatusidleNothing is happening.

TanStack Query uses the same values as strings.

QueryState​

QueryState<TQueryData> is what the cache entry itself holds, before any observer's select, placeholderData or staleTime applies. Read it from Query.state — in a cache listener, a QueryFilters predicate, or a RefetchInterval.dynamic or StaleTime.dynamic callback. It is flat rather than sealed, because the counters survive every transition.

It is publicly constructible so that a persistence layer can restore an entry (QueryCache.build, Query.setState). A success state must have hasData: true, or it is rejected with an ArgumentError. The no-argument constructor is the initial state: pending, idle, no data, every counter at zero.

NameTypeDefaultMeaning
statusQueryStatuspendingWhat the query holds.
fetchStatusFetchStatusidleWhat the query is doing.
hasDataboolfalseWhether data is meaningful: true once the query has resolved to data, even null data; stays true through a later error. No TanStack counterpart.
dataTQueryData?nullThe cached data. Meaningful only while hasData is true.
dataUpdateCountint0How many times data has been written, by fetches and setQueryData alike.
dataUpdatedAtDateTime?nullWhen data was last written.
errorObject?nullWhy the last fetch failed. Cleared by the next success, and by the start of a new fetch on a query without data; a query with data keeps it alongside the error while it refetches.
errorStackTraceStackTrace?nullThe stack trace of error. No TanStack counterpart.
errorUpdateCountint0Errors over the query's whole life. Never goes down.
consecutiveErrorCountint0Fetches in a row that failed, retries exhausted. Back to zero with the next fetched data; unchanged by a manual write or a cancelled fetch. No TanStack counterpart.
errorUpdatedAtDateTime?nullWhen the query last ended in an error. Not cleared with error.
fetchFailureCountint0Failed attempts inside the current fetch; reset when a new fetch starts. Surfaces as QueryResult.failureCount.
fetchFailureReasonObject?nullWhat the latest failed attempt threw. Surfaces as QueryResult.failureReason.
fetchFailureStackTraceStackTrace?nullThe stack trace of fetchFailureReason. No TanStack counterpart.
fetchMetaObject?nullWhatever the fetch behaviour attached to the current fetch. Infinite queries carry the page direction here.
isInvalidatedboolfalseStale regardless of staleTime: set by invalidateQueries and by a fetch that finally fails; reset by the next successful fetch or data write.
isFetchedbool (getter)—dataUpdateCount + errorUpdateCount > 0. No TanStack counterpart.
copyWithmethod—This state with fields replaced. Pass hasData whenever you pass data; clearData, clearError, clearFetchFailure and clearFetchMeta set fields back to nothing. No TanStack counterpart.

QueryState compares by value; the stack traces take no part.

Infinite queries​

An infinite query is an ordinary query whose data is an InfiniteData, so its result is an ordinary QueryResult<InfiniteData<TPageData, TPageParam>> (or whatever select makes of it). There is no separate infinite result type. See infinite queries.

InfiniteData​

InfiniteData<TPageData, TPageParam>

NameTypeMeaning
pagesList<TPageData>The pages in order. A forward fetch appends, a backward fetch prepends, maxPages drops from the far end.
pageParamsList<TPageParam>The param each page was fetched with, index for index with pages.
isEmptyboolpages.isEmpty. A fetched value always holds at least one page; an empty one comes from initialData or setQueryData. No TanStack counterpart.
flattenIterable<TItem> flatten<TItem>()Every item of every page, when each page is an Iterable<TItem>. A page that is not throws an ArgumentError before iteration starts. Name the item type: without it the result is Iterable<dynamic>. No TanStack counterpart.
copyWithmethodThis value with either list replaced. A replacement list is copied into an unmodifiable one; a list passed back unchanged keeps its identity. No TanStack counterpart.

The constructor refuses lists of different lengths with an ArgumentError. A value built by a fetch or by copyWith holds unmodifiable lists, so pages.add(…) on fetched data read back from the cache throws UnsupportedError. A value you build yourself and pass in — as initialData or through setQueryData — can keep the growable lists you gave it until the next fetch replaces it. Either way, write a new value with setQueryData rather than changing the lists in place. Equality is element by element over both lists.

Paging members​

hasNextPage, fetchNextPage and the direction flags are not on the result. The result has one shape for every kind of query, so the paging surface lives on InfiniteQueryObserver and, in Flutter, on InfiniteQueryController, which every infinite read style hands you. A change in any of these flags notifies listeners even when the result itself is unchanged. (TanStack Query puts them on its infinite result object.)

NameTypeMeaning
hasNextPageboolgetNextPageParam returns a param for the last page held. False before the first page arrives.
hasPreviousPageboolgetPreviousPageParam is set and returns a param for the first page held. False before the first page arrives.
isFetchingNextPageboolThe fetch in flight is a fetchNextPage.
isFetchingPreviousPageboolThe fetch in flight is a fetchPreviousPage.
isFetchNextPageErrorboolThe result is a QueryError that came from a fetchNextPage.
isFetchPreviousPageErrorboolThe result is a QueryError that came from a fetchPreviousPage.
isRefetchingboolThe pages already held are being refetched. Unlike the result's own isRefetching, a page being added does not count.
isRefetchErrorboolA refetch of the held pages failed, as opposed to a page fetch.
fetchNextPageFuture<QueryResult<TData>> fetchNextPage({bool cancelRefetch = true})Fetches the page after the last one and appends it. Does nothing when hasNextPage is false; on a query with no pages it loads the first one. Completes with the result, never with an error.
fetchPreviousPageFuture<QueryResult<TData>> fetchPreviousPage({bool cancelRefetch = true})The mirror of fetchNextPage, prepending.

With cancelRefetch: true a fetch already running on a query that holds pages is cancelled; with false, or while the first page is loading, the call joins it and adds no page. Check isFetchingNextPage first so a scroll listener firing repeatedly does not cancel its own page fetch.

MutationResult​

MutationResult<TData, TVariables> is what a MutationObserver reports and what every mutation read style in Flutter hands a widget. It is sealed, with one case per MutationStatus:

CaseWhen
MutationIdleNothing submitted yet, or reset since.
MutationPendingA run is in flight — onMutate, the mutation function, or the settling callbacks — or paused (isPaused).
MutationSuccessThe last run returned, and its success callbacks have run.
MutationErrorThe last run failed for good, and its error callbacks have run. A cancelled run fails with a CancelledError.

See mutations.

NameTypeOn which casesMeaning
statusMutationStatusallThe case, as an enum.
isIdleboolallThis is a MutationIdle.
isPendingboolallThis is a MutationPending. Handy for disabling a submit button.
isSuccessboolallThis is a MutationSuccess.
isErrorboolallThis is a MutationError.
dataOrNullTData?alldata on a success, null otherwise. TanStack: data.
errorOrNullObject?allerror on an error, null otherwise. TanStack: error.
dataTDataMutationSuccessWhat the mutation function returned.
errorObjectMutationErrorWhat the last attempt threw — or what a success callback threw, which counts the same.
stackTraceStackTraceMutationErrorWhere error was thrown. No TanStack counterpart.
variablesTVariables?allThe variables of the run in flight or last finished — what an optimistic UI shows while pending.
hasVariablesboolallWhether variables means anything: false while idle; tells a real null from none. No TanStack counterpart.
failureCountintallFailed attempts of the current run. Reset when a new run starts.
failureReasonObject?allWhat the latest failed attempt threw. null once an attempt succeeds or a new run starts.
isPausedboolall (set only while pending)The run is parked: offline under NetworkMode.online, a retry waiting for the foreground, or queued behind another mutation in its MutationScope.
submittedAtDateTime?allWhen the current run was submitted. null while idle.
mutatevoid Function(TVariables)allStarts a new run and returns at once. Errors go to the callbacks and the next result, never to the caller. Takes only the variables, so it passes as a plain callback.
mutateAsyncFuture<TData> Function(TVariables)allStarts a new run; completes with its data or throws its error, once its callbacks have run.
resetvoid Function()allDetaches from the mutation and goes back to MutationIdle. The mutation keeps running and still fires its callbacks.

Not on the result:

  • What onMutate returned. It is MutationState.onMutateResult (below), handed to the onSuccess, onError and onSettled callbacks. TanStack Query's result spreads the state and so also carries it as context.
  • Per-call callbacks. MutateCallbacks go through MutationObserver.mutate(variables, callbacks: …) or MutationController.mutate.
  • cancel. It is on MutationObserver and MutationController; see cancelling mutations.

Results compare by value; mutate, mutateAsync, reset and the stack trace take no part.

MutationStatus​

MutationStatus

ValueMeaning
idleNever run, or reset since. No data, no error, no variables.
pendingRunning or paused. Lasts until the run has finished, callbacks included: the cache's and the options' onSuccess/onError and onSettled, and the future onSettled returns. The per-call callbacks run after it.
successThe last run resolved; data holds what it returned.
errorThe last run failed for good; error holds why.

MutationState​

MutationState<TData, TVariables, TOnMutateResult> is what a Mutation in the cache holds. Read it from Mutation.state — in a MutationStateObserver's select (see mutation state), a MutationCache listener, or MutationCache.findAll. A persistence layer builds one to restore an offline mutation through MutationCache.build. The no-argument constructor is the idle state.

NameTypeDefaultMeaning
statusMutationStatusidleWhere the mutation is in its life.
hasDataboolfalseWhether data is authoritative, so a function that returned null still reads as having data. No TanStack counterpart.
dataTData?nullWhat the last successful run returned. Cleared when a new run starts and when a run fails.
errorObject?nullWhy the last run failed; null unless status is error.
errorStackTraceStackTrace?nullThe stack trace of error. No TanStack counterpart.
variablesTVariables?nullThe variables of the run in flight or last finished.
hasVariablesboolfalseWhether a run has set variables; a null value is real once this is true. No TanStack counterpart.
onMutateResultTOnMutateResult?nullWhat onMutate returned for the run in flight or last finished — the rollback handle of an optimistic update. TanStack: context.
failureCountint0Failed attempts of the current run. Reset on success and when a new run starts; one more when the run settles in error.
failureReasonObject?nullWhat the last failed attempt threw. Kept while retries continue and after the run fails; cleared on success and when a new run starts.
isPausedboolfalseThe run is parked: network, foreground, or its scope.
submittedAtDateTime?nullWhen the current or last run was submitted.
copyWithmethod—A copy with fields replaced; clearData, clearError and clearFailureReason set fields back to nothing. No TanStack counterpart.

A restored pending state needs variables unless TVariables is nullable, and a success state needs hasData unless TData is nullable or void; anything else is rejected with an ArgumentError. MutationState compares by value; errorStackTrace takes no part.

CombinedResult​

CombinedResult<T> is what several QueryResults amount to together, with every source's data run through a combiner you supply. It is sealed, with three cases, decided by these rules in order:

  1. A source that is a QueryError without stale data makes the whole a CombinedError — the first such source, in order. It wins over a source that is still loading.
  2. Otherwise a QueryPending source makes the whole a CombinedPending.
  3. Otherwise every source has data — a success's, or the stale data of a failed refetch — and the whole is a CombinedData. A failed refetch shows up as refetchError, not as an error state.

The combiner runs only in the third case. See combining queries. TanStack Query offers the same idea as useQueries({ combine }), whose return value is whatever the combiner builds; none of the fields below has a TanStack name.

NameTypeOn which casesMeaning
isFetchingboolallAny source is fetching.
isPausedboolallAny source is paused.
isPendingboolallThis is a CombinedPending.
isErrorboolallThis is a CombinedError.
hasDataboolallThis is a CombinedData.
dataOrNullT?allThe combiner's result on a CombinedData, null otherwise.
refetchFuture<void> refetch({bool cancelRefetch = true})allRefetches every source through its own refetch, passing cancelRefetch on. Two combinations sharing a source each refetch it; pass false to one of them to join instead.
retryFuture<void> retry({bool cancelRefetch = true})allRefetches only the sources in error, an optional() source whose query failed included.
errorObjectCombinedErrorWhat the first failed source threw.
stackTraceStackTraceCombinedErrorThe stack trace that came with error.
dataTCombinedDataWhat the combiner returned.
refetchErrorObject?CombinedDataWhat the first source whose background refetch failed threw; its stale data is part of data. null when none did.
refetchErrorStackTraceStackTrace?CombinedDataThe stack trace that came with refetchError.
isPlaceholderDataboolCombinedDataAny source is showing placeholder data.
isStaleboolCombinedDataAny source's data is stale by its own staleTime.

Two combined results are equal when they are the same case with equal isFetching, isPaused and payload (the error; or the data, refetchError, isPlaceholderData and isStale). The sources' refetch closures take no part.

Building one​

A CombinedResult is never constructed directly. It comes from these extensions, which only read the results you already have — from observers, controllers or any read style.

NameOnSignatureMeaning
combinea record of two to six QueryResults (CombineQueryResults2 … CombineQueryResults6)combine<R>(R Function(A a, B b, …) combiner, {CombineMemo<R>? memo, List<Object?>? keys})Each source keeps its own data type; the combiner gets each source's data in record order.
combineList<QueryResult<T>> (CombineQueryResultList)combine<R>(R Function(List<T> values) combiner, {CombineMemo<R>? memo, List<Object?>? keys})The same rules over a list of one type, such as a QueriesObserver's results. An empty list is data.
combineWithList<QueryResult<T>>combineWith<A, R>(QueryResult<A> other, R Function(List<T> values, A other) combiner, {CombineMemo<R>? memo, List<Object?>? keys})The list plus one source of another type — typically the query the list was derived from — as one combination, other first in order.
optionalQueryResult<T> (OptionalQueryResult)QueryResult<T?> optional()Marks a source the combination must neither wait for nor fail with. With data it is the result itself; without, a QuerySuccess holding null with the same fetchStatus and refetch, so isFetching and retry() still see it.

Past six sources, combine a list typed by what the sources have in common — <QueryResult<Object?>>[…] at worst — and cast in the combiner. A CombinedResult is not itself a source, so combinations do not nest.

CombineMemo and keys​

CombineMemo<T> remembers the last combination. Keep one per call site (a State field, for example) and pass it as memo:. The combiner is then skipped while every source's data is the identical instance it was last time — the normal case for a refetch that changed nothing, thanks to structural sharing — and when it does run, its output is structurally shared with the previous one.

A memo cannot see what the combiner captures. With a memo, the combiner must be a function of the sources and of keys alone: name everything else it reads in keys: (compared with ==), or do that work after combine. keys without a memo does nothing.