{"record":{"id":"409165fcd72236be","repo":"pentaho/pentaho-kettle","slug":"getjobstatusservlet-error-unabletogetjobstatusinxml","errorCode":"GetJobStatusServlet.Error.UnableToGetJobStatusInXML","errorMessage":"GetJobStatusServlet.Error.UnableToGetJobStatusInXML","messagePattern":"GetJobStatusServlet\\.Error\\.UnableToGetJobStatusInXML","errorType":"http","errorClass":"ServletException","httpStatus":500,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/www/GetJobStatusServlet.java","lineNumber":313,"sourceCode":"            //\n            jobStatus.setResult( job.getResult() ); // might be null\n\n\n            String xml = jobStatus.getXML();\n            data = xml.getBytes( Charset.forName( Const.XML_ENCODING ) );\n            out = response.getOutputStream();\n            response.setContentLength( XML_HEADER.length + data.length );\n            out.write( XML_HEADER );\n            out.write( data );\n            out.flush();\n            if ( finishedOrStopped && ( jobStatus.isFinished() || jobStatus.isStopped() ) && logId != null ) {\n              cache.put( logId, xml, startLineNr );\n            }\n          }\n          response.flushBuffer();\n        } catch ( KettleException e ) {\n          response.setStatus( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );\n          throw new ServletException( BaseMessages.getString( PKG, \"GetJobStatusServlet.Error.UnableToGetJobStatusInXML\" ), e );\n        }\n      } else {\n\n        PrintWriter out = response.getWriter();\n\n        int lastLineNr = KettleLogStore.getLastBufferLineNr();\n        int tableBorder = 0;\n\n        response.setContentType( \"text/html\" );\n\n        out.println( \"<HTML>\" );\n        out.println( \"<HEAD>\" );\n        out\n          .println( \"<TITLE>\"\n            + BaseMessages.getString( PKG, \"GetJobStatusServlet.KettleJobStatus\" ) + \"</TITLE>\" );\n        if ( EnvUtil.getSystemProperty( Const.KETTLE_CARTE_REFRESH_STATUS, \"N\" ).equalsIgnoreCase( \"Y\" ) ) {\n          out.println( \"<META http-equiv=\\\"Refresh\\\" content=\\\"10;url=\"\n            + convertContextPath( GetJobStatusServlet.CONTEXT_PATH ) + \"?name=\"","sourceCodeStart":295,"sourceCodeEnd":331,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/www/GetJobStatusServlet.java#L295-L331","documentation":"Thrown by GetJobStatusServlet.doGet when generating the XML job-status document fails with a KettleException. The servlet catches the KettleException, sets HTTP 500, and rethrows as a ServletException with this generic message; the real cause is attached.","triggerScenarios":"GET /kettle/jobStatus/?name=<job>&xml=Y when building the status XML fails — e.g. the JobExecutionConfiguration/status XML generation throws, the log buffer cannot be read, or the job's internal state is inconsistent while serializing.","commonSituations":"Monitoring clients polling job status in XML mode hit HTTP 500 while a job is stopping/finished; log store issues or corrupt job metadata during XML serialization; cache-enabled polling after a job was removed mid-request.","solutions":["Inspect the wrapped KettleException cause in the server log for the real failure (getLogText OOM, XML generation, etc.).","If caused by log size OOM, reduce the requested log range (use /kettle/jobStatus/ without xml or tail lines) or increase heap / trim KettleLogStore buffer size.","Retry the status request once the job reaches a stable state (finished/stopped); avoid polling during rapid start/stop cycles.","Clear/disable the servlet status cache (useXML with cache bypass parameters) if a stale cached entry is implicated."],"exampleFix":"// before (client)\nString xml = httpGet(\"/kettle/jobStatus/?name=myjob&xml=Y\");\n// after\ntry {\n  String xml = httpGet(\"/kettle/jobStatus/?name=myjob&xml=Y\");\n} catch (HttpServerErrorException e) {\n  // HTTP 500: inspect server log for wrapped KettleException cause, retry after job stabilizes\n  retryWithBackoff(\"/kettle/jobStatus/?name=myjob&xml=Y\");\n}","handlingStrategy":"try-catch","validationCode":"// client: only request XML once the job reports a stable state\nString state = httpGet(\"/kettle/jobStatus/?name=\" + jobName); // non-XML poll first\nboolean safeToPollXml = state.contains(\"Finished\") || state.contains(\"Stopped\") || state.contains(\"Running\");","typeGuard":null,"tryCatchPattern":"try {\n  String xml = httpGet(\"/kettle/jobStatus/?name=\" + jobName + \"&xml=Y\");\n} catch (HttpServerErrorException e) { // 500 with this message\n  log.warn(\"jobStatus XML failed; inspect server log cause\", e);\n  retryWithBackoff(() -> httpGet(\"/kettle/jobStatus/?name=\" + jobName + \"&xml=Y\"), 3);\n}","preventionTips":["Poll non-XML status first and request XML only for stable job states.","Cap job log verbosity and buffer size so XML assembly cannot OOM.","Monitor server heap; alert before memory pressure breaks status serialization.","Retry with backoff instead of tight polling loops."],"tags":["servlet","xml","job-status","http-500"],"backgroundTag":"http-error-response","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}