{"record":{"id":"5ff4fb4f45ad9fb6","repo":"apache/beam","slug":"job-does-not-exist","errorCode":null,"errorMessage":"Job {} does not exist","messagePattern":"Job (.+?) does not exist","errorType":"exception","errorClass":"LookupError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/runners/portability/abstract_job_service.py","lineNumber":151,"sourceCode":"        pipeline=self._jobs[request.job_id].get_pipeline())\n\n  def Cancel(\n      self,\n      request: beam_job_api_pb2.CancelJobRequest,\n      context=None,\n      timeout=None) -> beam_job_api_pb2.CancelJobResponse:\n    self._jobs[request.job_id].cancel()\n    return beam_job_api_pb2.CancelJobResponse(\n        state=self._jobs[request.job_id].get_state()[0])\n\n  def GetStateStream(self,\n                     request,\n                     context=None,\n                     timeout=None) -> Iterator[beam_job_api_pb2.JobStateEvent]:\n    \"\"\"Yields state transitions since the stream started.\n      \"\"\"\n    if request.job_id not in self._jobs:\n      raise LookupError(\"Job {} does not exist\".format(request.job_id))\n\n    job = self._jobs[request.job_id]\n    for state, timestamp in job.get_state_stream():\n      yield make_state_event(state, timestamp)\n\n  def GetMessageStream(\n      self,\n      request,\n      context=None,\n      timeout=None) -> Iterator[beam_job_api_pb2.JobMessagesResponse]:\n    \"\"\"Yields messages since the stream started.\n      \"\"\"\n    if request.job_id not in self._jobs:\n      raise LookupError(\"Job {} does not exist\".format(request.job_id))\n\n    job = self._jobs[request.job_id]\n    for msg in job.get_message_stream():\n      if isinstance(msg, tuple):","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/runners/portability/abstract_job_service.py#L133-L169","documentation":"GetStateStream yields job state transitions since stream start. It raises LookupError when request.job_id is not a key in the service's in-memory _jobs registry, i.e. this service instance has no record of that job.","triggerScenarios":"Calling the BeamJobApi GetStateStream RPC with a job_id never registered on this service instance, or with a job_id from before the service process restarted.","commonSituations":"Client connecting to a restarted job server (in-memory registry lost); stale or typo'd job_id; submitting to one service instance and polling on another.","solutions":["Use the job_id returned by the submit/run call against the same, still-running service instance.","If the service was restarted, re-submit the pipeline since job state is not persisted.","Inspect the server's self._jobs keys to confirm which jobs exist."],"exampleFix":"// before\nstub.GetStateStream(beam_job_api_pb2.GetJobStateRequest(job_id=stale_id))\n// after\nresp = stub.Run(beam_job_api_pb2.RunJobRequest(...))\nstub.GetStateStream(beam_job_api_pb2.GetJobStateRequest(job_id=resp.job_id))","handlingStrategy":"try-catch","validationCode":"# only call with a job_id returned by this service instance\nassert job_id in known_job_ids_from_submit_responses","typeGuard":null,"tryCatchPattern":"try:\n    for ev in stub.GetStateStream(req):\n        handle(ev)\nexcept LookupError:\n    job_id = resubmit_pipeline()  # registry is in-memory; server likely restarted","preventionTips":["Keep the job_id returned by the submit/run call; never hardcode one.","Treat the server's job registry as ephemeral; a restart means job loss.","Poll state on the same service instance that ran the job."],"tags":["python","apache-beam","grpc-job-service","lookup"],"backgroundTag":"resource-not-found","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}