{"record":{"id":"03991c0a7158e52d","repo":"apache/hadoop","slug":"job-in-state-instead-of","errorCode":null,"errorMessage":"Job in state {} instead of {}","messagePattern":"Job in state (.+?) instead of (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/Job.java","lineNumber":301,"sourceCode":"   * parameter.\n   * \n   * @param cluster cluster\n   * @param status job status\n   * @param conf job configuration\n   * @return the {@link Job} , with no connection to a cluster yet.\n   * @throws IOException\n   */\n  @Private\n  public static Job getInstance(Cluster cluster, JobStatus status, \n      Configuration conf) throws IOException {\n    Job job = getInstance(status, conf);\n    job.setCluster(cluster);\n    return job;\n  }\n\n  private void ensureState(JobState state) throws IllegalStateException {\n    if (state != this.state) {\n      throw new IllegalStateException(\"Job in state \"+ this.state + \n                                      \" instead of \" + state);\n    }\n\n    if (state == JobState.RUNNING && cluster == null) {\n      throw new IllegalStateException\n        (\"Job in state \" + this.state\n         + \", but it isn't attached to any job tracker!\");\n    }\n  }\n\n  /**\n   * Some methods rely on having a recent job status object.  Refresh\n   * it, if necessary\n   */\n  synchronized void ensureFreshStatus() \n      throws IOException {\n    if (System.currentTimeMillis() - statustime > MAX_JOBSTATUS_AGE) {\n      updateStatus();","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-core/src/main/java/org/apache/hadoop/mapreduce/Job.java#L283-L319","documentation":"org.apache.hadoop.mapreduce.Job is a small state machine (DEFINE on construction, RUNNING after submit(), then finished). Most setters call ensureState(JobState.DEFINE) and status/control methods call ensureState(JobState.RUNNING). When a method is invoked from the wrong state, ensureState throws IllegalStateException naming the actual state and the required one (e.g. 'Job in state RUNNING instead of DEFINE').","triggerScenarios":"Calling setNumReduceTasks/setMapperClass/setInputPath/setProfileTaskRange after job.submit() (state has moved to RUNNING); calling getStatus(), killTask(), or monitorAndPrintJob() on a freshly built Job that was never submitted (still DEFINE); a second check in ensureState also fires when a RUNNING job has no Cluster attached (job obtained via getInstance(status, conf) without a cluster).","commonSituations":"Retry logic that catches a failed run, tweaks the same Job object and resubmits it; wrappers that poll status before submit; code migrated from the old mapred JobConf API, where a JobConf could be freely reused across submissions.","solutions":["Treat Job as single-use: build a new Job.getInstance(conf), do ALL configuration, then submit once","For a rerun with changes, write values into the Configuration first, then construct a fresh Job from it","Move getStatus/killTask/monitorAndPrintJob calls strictly after submit(), and gate polling with job.isComplete()","If you see 'RUNNING ... but it isn't attached to any job tracker', obtain the Job from a Cluster (Cluster.getJob(id)) so it has a client attached"],"exampleFix":"// before\njob.submit();\nif (runFailed) {\n  job.setNumReduceTasks(1); // IllegalStateException: Job in state RUNNING instead of DEFINE\n  job.submit();\n}\n\n// after\nif (runFailed) {\n  conf.setInt(MRJobConfig.NUM_REDUCES, 1);\n  job = Job.getInstance(conf); // fresh DEFINE-state job\n  job.submit();\n}","handlingStrategy":"validation","validationCode":"// single-use Job wrapper that prevents wrong-state calls\nfinal boolean[] submitted = {false};\nRunnable safeSubmit = () -> {\n  if (submitted[0]) throw new IllegalStateException(\"Job already submitted; create a new Job for a rerun\");\n  job.submit();\n  submitted[0] = true;\n};\n// all setters must be called before safeSubmit.run()","typeGuard":null,"tryCatchPattern":"try {\n  job.setNumReduceTasks(2);\n} catch (IllegalStateException e) {\n  // message shape: 'Job in state RUNNING instead of DEFINE'\n  if (e.getMessage().contains(\"instead of\")) {\n    throw new IllegalStateException(\"Configure the job before submit(), or build a new Job\", e);\n  }\n  throw e;\n}","preventionTips":["Treat Job as immutable-after-submit: finish configuration, then submit, then only status/kill calls","For reruns, mutate the Configuration and construct Job.getInstance(conf) fresh","Never keep a Job across user sessions to reconfigure later"],"tags":["lifecycle","state-machine","illegal-state","job-submission","mapreduce"],"backgroundTag":"illegal-state-transition","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}