{"record":{"id":"103685f0ee3cc244","repo":"apache/hadoop","slug":"bad-request-missing-job-id","errorCode":null,"errorMessage":"Bad Request: Missing job ID","messagePattern":"Bad Request: Missing job ID","errorType":"http","errorClass":"RuntimeException","httpStatus":400,"severity":"error","filePath":"hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AppController.java","lineNumber":412,"sourceCode":"  boolean checkAccess(Job job) {\n    String remoteUser = request().getRemoteUser();\n    UserGroupInformation callerUGI = null;\n    if (remoteUser != null) {\n      callerUGI = UserGroupInformation.createRemoteUser(remoteUser);\n    }\n    if (callerUGI != null && !job.checkAccess(callerUGI, JobACL.VIEW_JOB)) {\n      return false;\n    }\n    return true;\n  }\n\n  /**\n   * Ensure that a JOB_ID was passed into the page.\n   */\n  public void requireJob() {\n    if ($(JOB_ID).isEmpty()) {\n      badRequest(\"missing job ID\");\n      throw new RuntimeException(\"Bad Request: Missing job ID\");\n    }\n\n    JobId jobID = MRApps.toJobID($(JOB_ID));\n    app.setJob(app.context.getJob(jobID));\n    if (app.getJob() == null) {\n      notFound($(JOB_ID));\n      throw new RuntimeException(\"Not Found: \" + $(JOB_ID));\n    }\n\n    /* check for acl access */\n    Job job = app.context.getJob(jobID);\n    if (!checkAccess(job)) {\n      accessDenied(\"User \" + request().getRemoteUser() + \" does not have \" +\n          \" permission to view job \" + $(JOB_ID));\n      throw new RuntimeException(\"Access denied: User \" +\n          request().getRemoteUser() + \" does not have permission to view job \" +\n          $(JOB_ID));\n    }","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/main/java/org/apache/hadoop/mapreduce/v2/app/webapp/AppController.java#L394-L430","documentation":"AppController.requireJob guards every job-scoped page of the AM web UI: when the 'job.id' query parameter is missing or empty it sends a 400 (badRequest) and throws RuntimeException(\"Bad Request: Missing job ID\") to abort rendering.","triggerScenarios":"Opening /job, /tasks, /attempts, /task, /conf or /counters on the AM UI without ?job.id=job_..., or with an empty value (?job.id=).","commonSituations":"Bookmarked page whose query string was cut off; templating or scraping code that drops the parameter; manual URL construction.","solutions":["Append the parameter: /job?job.id=job_1401318629735_0001","Start at the AM home page and follow the application master link - generated URLs always carry job.id","Check for URL-encoding mistakes that empty the value"],"exampleFix":"// before\nhttp://am-host:8099/job\n// 400 Bad Request: Missing job ID\n\n// after\nhttp://am-host:8099/job?job.id=job_1401318629735_0001","handlingStrategy":"validation","validationCode":"if (jobId == null || jobId.isEmpty() || !jobId.startsWith(\"job_\")) {\n  throw new IllegalArgumentException(\"job.id query parameter is required: ?job.id=job_<ts>_<seq>\");\n}\nString url = \"http://\" + amHost + \":8099/job?job.id=\" + URLEncoder.encode(jobId, UTF_8);","typeGuard":"static boolean isWellFormedJobId(String jid) {\n  return jid != null && jid.startsWith(\"job_\")\n      && jid.split(\"_\").length == 3;\n}","tryCatchPattern":null,"preventionTips":["Centralize AM UI URL construction in one helper that always appends job.id","Test scraping links end-to-end so dropped parameters fail in CI","Enter through the AM home page and follow its links"],"tags":["mapreduce","web-ui","http-400","applicationmaster","query-parameter"],"backgroundTag":"missing-required-query-parameter","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}