{"record":{"id":"66779afd89009cc5","repo":"apache/beam","slug":"received-timer-after-inbound-timer-receiver-is-done-for","errorCode":null,"errorMessage":"Received timer after inbound timer receiver is done for instruction %s, transform %s, and timer family %s.","messagePattern":"Received timer after inbound timer receiver is done for instruction (.+?), transform (.+?), and timer family (.+?)\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/fn/data/BeamFnDataInboundObserver.java","lineNumber":259,"sourceCode":"    while (timerElements.hasNext()) {\n      Elements.Timers timers = timerElements.next();\n      Map<String, EndpointStatus<TimerEndpoint<?>>> timerFamilyIdToEndpoints =\n          transformIdToTimerFamilyIdToTimerEndpoint.get(timers.getTransformId());\n      if (timerFamilyIdToEndpoints == null) {\n        throw new IllegalStateException(\n            String.format(\n                \"Unable to find inbound timer receiver for instruction %s, transform %s, and timer family %s.\",\n                timers.getInstructionId(), timers.getTransformId(), timers.getTimerFamilyId()));\n      }\n      EndpointStatus<TimerEndpoint<?>> endpoint =\n          timerFamilyIdToEndpoints.get(timers.getTimerFamilyId());\n      if (endpoint == null) {\n        throw new IllegalStateException(\n            String.format(\n                \"Unable to find inbound timer receiver for instruction %s, transform %s, and timer family %s.\",\n                timers.getInstructionId(), timers.getTransformId(), timers.getTimerFamilyId()));\n      } else if (endpoint.isDone) {\n        throw new IllegalStateException(\n            String.format(\n                \"Received timer after inbound timer receiver is done for instruction %s, transform %s, and timer family %s.\",\n                timers.getInstructionId(), timers.getTransformId(), timers.getTimerFamilyId()));\n      }\n      InputStream inputStream = timers.getTimers().newInput();\n      Coder<Object> coder = (Coder<Object>) endpoint.endpoint.getCoder();\n      FnDataReceiver<Object> receiver = (FnDataReceiver<Object>) endpoint.endpoint.getReceiver();\n      while (inputStream.available() > 0) {\n        receiver.accept(coder.decode(inputStream));\n      }\n      if (timers.getIsLast()) {\n        endpoint.isDone = true;\n        numEndpointsThatAreIncomplete -= 1;\n      }\n    }\n    return numEndpointsThatAreIncomplete == 0;\n  }\n","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/fn/data/BeamFnDataInboundObserver.java#L241-L277","documentation":"multiplexElements throws IllegalStateException when timers arrive for an (instruction, transform, timerFamily) endpoint that is already marked done. The timer endpoint was terminated and late timer data is still arriving for it.","triggerScenarios":"Harness sends Elements.Timers after the timer endpoint completed — racing shutdown, duplicated isLast batches, or redelivery of timers after the bundle finished during awaitCompletion.","commonSituations":"Network buffering delays timer messages past bundle completion; harness keeps streaming after isLast; runner aborts the bundle while timers are in flight.","solutions":["Stop streaming timers for a family once its endpoint is done; check endpoint state before sending.","Ensure isLast semantics for Timers halt the harness stream at the right point.","Catch IllegalStateException in awaitCompletion and fail the bundle; look for version mismatches or races if it recurs."],"exampleFix":"// before\ntimerReceiver.accept(timers); // may race with endpoint close\n// after\nif (!endpoint.isDone) {\n  timerReceiver.accept(timers);\n}","handlingStrategy":"try-catch","validationCode":"if (endpoint.isDone) { /* stop streaming timers */ }","typeGuard":null,"tryCatchPattern":"try { observer.awaitCompletion(); } catch (IllegalStateException e) { failBundle(instructionId, e); }","preventionTips":["Stop streaming timers once the family endpoint is done","Honor Timers isLast semantics","Handle shutdown races by failing the bundle cleanly"],"tags":["java","beam-fn","timers","race-condition"],"backgroundTag":"invalid-state-transition","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-15T02:17:10.978Z"}