apache/beam · error · Error
Not expecting timers.
Error message
Not expecting timers.
What it means
The TypeScript worker's source/operator startBundle wires a sendTimers callback that unconditionally throws. This operator type does not expect timers to be emitted, so receiving them signals an internal invariant violation in bundle execution.
Solutions
- Avoid timers in transforms run by this operator; restructure to use windowing-only behavior.
- Upgrade the apache-beam TypeScript SDK to a version supporting timers if available.
- Move the timer-dependent transform to the Python or Java SDK.
Example fix
// before
context.setTimer("fire", window, Duration.millis(0));
// after
// emit directly or rely on window triggers instead of timers Defensive patterns
Strategy: validation
Validate before calling
// assert transforms don't call setTimer before submitting to the TS worker
if (transformRequiresTimers(dofn)) throw new Error("Refactor: timers unsupported here"); Try / catch
try {
await worker.startBundle();
} catch (e) {
if (e.message === "Not expecting timers.") {
// redesign pipeline without timers or switch SDK
}
} Prevention
- Avoid timer APIs in transforms executed by the TS worker.
- Match runner and SDK versions to known-supported feature sets.
When it happens
Trigger: During a bundle, the user transform (or windowing logic) emits a timer while running under this operator whose sendTimers is a throw-stub.
Common situations: Stateful/timer-using DoFns executed by the TypeScript worker; combining windowing features with an operator that doesn't support timer output; SDK feature gap.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Timers not yet supported.
- Data should not come in via process.
- A cannot be expanded
- Cannot access timer in non-window observing context.
- Cannot access timerFamily in non-window observing context.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/bf2b52c517f76c65.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/typescript/src/apache_beam/worker/operators.ts:244
this_.lastProcessedElement += 1;
const maybePromise = this_.receiver.receive(
this_.coder.decode(reader, CoderContext.needsDelimiters),
);
if (maybePromise !== NonPromise) {
await maybePromise;
}
// Periodically yield control explicitly to allow other tasks
// (including splits requests) to get scheduled.
// Note that waiting on a resolved promise is not sufficient, so
// we do this in addition to the above loop.
if (Date.now() - lastYield > 100 /* milliseconds */) {
await new Promise((r) => setTimeout(r, 0));
lastYield = new Date().getTime();
}
}
},
sendTimers: async function (timerFamilyId: string, timers: Uint8Array) {
throw Error("Not expecting timers.");
},
close: function () {
endOfDataResolve();
},
onError: function (error: Error) {
endOfDataReject(error);
},
},
);
}
process(wvalue: WindowedValue<unknown>): ProcessResult {
throw Error("Data should not come in via process.");
}
split(
desiredSplit: fnApi.ProcessBundleSplitRequest_DesiredSplit,
): fnApi.ProcessBundleSplitResponse_ChannelSplit | undefined {View on GitHub (pinned to 12126d8942)