apache/druid · error · MSQException
BroadcastTablesTooLarge
BroadcastTablesTooLarge
Error message
BroadcastTablesTooLargeFault: broadcast tables exceed reserved memory %s
What it means
Raised when the total byte size of broadcast tables read into memory during a broadcast join exceeds the memory reserved for the broadcast join (BroadcastTablesTooLargeFault wrapped in MSQException). Broadcast joins materialize the entire right-hand tables on every worker, so Druid enforces a reserved-memory cap and aborts the query rather than risk heap exhaustion.
Source
Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/querykit/BroadcastJoinSegmentMapFnProcessor.java:252
* Reads up to one frame from each readable side channel, and uses them to incrementally build up joinable
* broadcast tables.
*
* @param readableInputs all readable input channel numbers, including non-side-channels
* @return whether side channels have been fully read
*/
boolean buildBroadcastTablesIncrementally(final IntSet readableInputs)
{
final IntIterator inputChannelIterator = readableInputs.iterator();
while (inputChannelIterator.hasNext()) {
final int channelNumber = inputChannelIterator.nextInt();
if (sideChannelNumbers.contains(channelNumber) && channels.get(channelNumber).canRead()) {
final Frame frame = channels.get(channelNumber).readFrame();
memoryUsed += frame.numBytes();
if (memoryUsed > memoryReservedForBroadcastJoin) {
throw new MSQException(
new BroadcastTablesTooLargeFault(
memoryReservedForBroadcastJoin,
Optional.ofNullable(query)
.map(q -> q.context().getString(PlannerContext.CTX_SQL_JOIN_ALGORITHM))
.map(JoinAlgorithm::fromString)
.orElse(null)
)
);
}
addFrame(channelNumber, frame);
}
}
for (int channelNumber : sideChannelNumbers) {
if (!channels.get(channelNumber).isFinished()) {
return false;
}View on GitHub (pinned to 9b90983fd2)
Solutions
- Reduce the size of the broadcast side of the join (filter rows/columns before joining).
- Force a sort-merge (partitioned) join instead: set "sqlJoinAlgorithm":"sortMerge" in the query context.
- Increase memory reserved for broadcast joins (druid.msq.memory.reservedForBroadcastJoin / stage memory tuning) or add more workers so per-worker load drops.
- Pre-materialize and downcast the small table, or filter the large table upstream.
Example fix
// before
SELECT * FROM big_events t JOIN dims d ON t.dim_id = d.id; // broadcast join
// after
SELECT * FROM big_events t
JOIN dims d ON t.dim_id = d.id
-- context: {"sqlJoinAlgorithm": "sortMerge"} Defensive patterns
Strategy: try-catch
Validate before calling
// estimate broadcast size before query: sum of bytes of small-side tables
long broadcastBytes = estimateTableBytes(smallSideTables);
if (broadcastBytes > reservedBroadcastMemory) { /* switch to sortMerge */ } Try / catch
try {
result = runMsqQuery(query);
} catch (MSQException e) {
if (e.getFault() instanceof BroadcastTablesTooLargeFault) {
query.context().put("sqlJoinAlgorithm", "sortMerge");
result = runMsqQuery(query); // retry with partitioned join
} else throw e;
} Prevention
- Keep broadcast-side tables small (filter rows and columns).
- Set sqlJoinAlgorithm=sortMerge when join inputs may be large.
- Size memoryReservedForBroadcastJoin to your largest expected dimension table.
When it happens
Trigger: Running a broadcast (hash) join in MSQ where the sum of broadcast frame sizes read in BroadcastTablesTooLargeFault.buildBroadcastTablesIncrementally exceeds memoryReservedForBroadcastJoin (from memory reserve config / cluster capacity).
Common situations: Joining large dimension tables that were assumed small; context join algorithm set to broadcast inadvertently (default for equi-joins with small tables); cluster with low memory reserve for broadcast joins.
Understand the failure class
Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.
Related errors
- Column[%d] is not a valid column for segment[%s]
- Unknown
- Unknown
- No such outputChannelMode[%s]
- MSQFault from worker error report
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/0410b28d9943936d.
Report an issue: GitHub.