Loki Error Guide: 'too many chunks to fetch' — Narrow the Query or Raise max_chunks_per_query
Fix Loki 'too many chunks to fetch': understand max_chunks_per_query, why broad matchers and long ranges pull too many chunks, and how to tighten selectors, split ranges, or raise the limit safely.
- #loki
- #logging
- #troubleshooting
- #errors
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
Overview
Loki aborts a query when the number of chunks it would fetch from storage exceeds max_chunks_per_query. The querier returns:
query would fetch too many chunks to fetch (limit: 2000000): time range and selector are too broad, reduce the time range or add more specific label matchers
Each stream is stored as a sequence of chunks in object storage; a broad selector over a long range can reference millions of them. This limit protects queriers from loading an unbounded amount of data into memory and hammering object storage.
Symptoms
- A query fails instantly with
too many chunks to fetchbefore returning any lines. - The same query works over a shorter range or with a tighter matcher.
- Broad selectors like
{cluster="prod"}with no other label trigger it. - Querier logs show the chunk count and limit.
- Object-store GET rate spikes right before the query is aborted.
Common Root Causes
- Overly broad label matcher — selecting an entire cluster/namespace instead of a specific app/stream.
- Long time range — weeks of data across many streams multiplies chunk count.
- High stream cardinality — many streams (from high-cardinality labels) each contribute chunks.
- Small chunks — misconfigured
chunk_target_size/max_chunk_ageproducing many tiny chunks per stream. - Limit set conservatively —
max_chunks_per_querytoo low for a legitimate broad-but-bounded query. - Missing line filters — no early
|=filter to let Loki skip chunks by their bloom/stats.
Diagnostic Workflow
Check the configured limit:
limits_config:
max_chunks_per_query: 2000000
Estimate how much a selector will scan before running it fully — logcli stats show chunks and bytes:
logcli query '{cluster="prod"}' --since=24h --stats --limit=1 2>&1 | grep -i chunks
Tighten the selector so it matches fewer streams. Instead of:
{cluster="prod"} |= "timeout"
scope to the relevant service and add the filter early:
{cluster="prod", namespace="payments", app="checkout"} |= "timeout"
Split a wide range into windows that each stay under the limit:
logcli query '{namespace="payments"} |= "error"' \
--from="2026-06-01T00:00:00Z" --to="2026-06-02T00:00:00Z" --limit=5000
If chunks are tiny (many chunks per stream), tune chunk sizing so each stream produces fewer, larger chunks:
limits_config:
# ingester chunk targets
ingestion_rate_mb: 8
chunk_store_config:
chunk_cache_config:
embedded_cache:
enabled: true
# ingester block
ingester:
chunk_target_size: 1572864 # ~1.5MB target
chunk_idle_period: 30m
max_chunk_age: 2h
Example Root Cause Analysis
An engineer investigating a payment outage ran {cluster="prod"} |= "timeout" over the last 7 days and got too many chunks to fetch (limit: 2000000). Running the same selector with --stats over just 1 hour reported ~180k chunks — extrapolated across 7 days and the full cluster it was tens of millions, far over the limit.
Two issues compounded it. First, the selector matched every stream in prod when only namespace="payments" mattered. Scoping to {cluster="prod", namespace="payments", app="checkout"} cut the stream set by ~95%. Second, --stats showed an unusually high chunk count per stream because max_chunk_age was left at a short value, flushing many tiny chunks; raising chunk_target_size and max_chunk_age produced fewer, larger chunks going forward. With the tighter selector the 7-day query ran in seconds, and the limit stayed in place to protect the shared queriers — the query, not the limit, was the problem.
Prevention Best Practices
- Always scope queries with specific low-cardinality matchers (namespace, app, level) rather than cluster-wide selectors.
- Put line filters (
|=) early so Loki can skip chunks and reduce fetches. - Split long-range investigations into windowed queries under the chunk limit.
- Tune chunk sizing (
chunk_target_size,max_chunk_age,chunk_idle_period) so streams produce fewer, larger chunks. - Use
logcli --statswhile authoring dashboards to see chunk/byte cost before shipping. - Raise
max_chunks_per_queryonly per tenant for genuinely broad-but-bounded needs, and watch querier memory.
Quick Command Reference
# See chunk/byte cost of a selector
logcli query '{cluster="prod"}' --since=1h --stats --limit=1
# Scoped, filtered query
logcli query '{namespace="payments", app="checkout"} |= "timeout"' --since=24h
# Windowed long-range query
logcli query '{namespace="payments"}' --from="2026-06-01T00:00:00Z" --to="2026-06-02T00:00:00Z"
# Effective limit
logcli --addr=http://loki-gateway/ config | grep -i max_chunks_per_query
Conclusion
too many chunks to fetch means your selector and time range would pull more chunks than max_chunks_per_query allows — usually a cluster-wide matcher, a long range, high stream cardinality, or tiny chunks. Use logcli --stats to measure the cost, tighten the selector to the streams that matter, filter early, and split long ranges. Fix chunk sizing so streams flush fewer, larger chunks, and raise the limit only per tenant for legitimate broad queries. The limit is protecting your queriers and object storage — narrow the query rather than removing the guard.
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.