{"record":{"id":"30dec8ea5fa36496","repo":"pentaho/pentaho-kettle","slug":"error-while-closing-output-orabulkloader","errorCode":null,"errorMessage":"Error while closing output","messagePattern":"Error while closing output","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"plugins/oracle-bulk-loader/impl/src/main/java/org/pentaho/di/trans/steps/orabulkloader/OraBulkLoader.java","lineNumber":512,"sourceCode":"\n  public boolean processRow( StepMetaInterface smi, StepDataInterface sdi ) throws KettleException {\n    meta = (OraBulkLoaderMeta) smi;\n    data = (OraBulkLoaderData) sdi;\n\n    try {\n      Object[] r = getRow(); // Get row from input rowset & set row busy!\n      if ( r == null ) {\n        // no more input to be expected...\n\n        setOutputDone();\n\n        if ( !preview ) {\n          if ( output != null ) {\n            // Close the output\n            try {\n              output.close();\n            } catch ( IOException e ) {\n              throw new KettleException( \"Error while closing output\", e );\n            }\n\n            output = null;\n          }\n\n          String loadMethod = meta.getLoadMethod();\n          if ( OraBulkLoaderMeta.METHOD_AUTO_END.equals( loadMethod ) ) {\n            // if this is the first line, we do not need to execute loader\n            // control file may not exists\n            if ( !first ) {\n              execute( meta, true );\n              sqlldrProcess = null;\n            }\n          } else if ( OraBulkLoaderMeta.METHOD_AUTO_CONCURRENT.equals( meta.getLoadMethod() ) ) {\n            try {\n              if ( sqlldrProcess != null ) {\n                int exitVal = sqlldrProcess.waitFor();\n                sqlldrProcess = null;","sourceCodeStart":494,"sourceCodeEnd":530,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/plugins/oracle-bulk-loader/impl/src/main/java/org/pentaho/di/trans/steps/orabulkloader/OraBulkLoader.java#L494-L530","documentation":"processRow() streams incoming rows to sqlldr's stdin through the 'output' writer; if closing that stream raises an IOException the step throws 'Error while closing output' with the original as cause. This happens while finalizing the pipe to the loader process, so sqlldr may not have received all data.","triggerScenarios":"output.close() throws IOException during processRow's close sequence for the non-preview path of the stream (conventional) load method.","commonSituations":"sqlldr process already died (broken pipe) so the stdin stream is no longer writable; disk/OS-level I/O problems; JVM-level stream state issues after the child terminated early.","solutions":["Check the sqlldr log — the child process usually crashed first (broken pipe); fix the root ORA- error from that log","Verify the sqlldr command/credentials so the process stays alive while data is streamed","Re-run the transformation; transient I/O errors on the pipe sometimes disappear","If it persists, inspect the cause stack trace for 'Broken pipe' to confirm the child died mid-stream"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  step.processRow( smi, sdi );\n} catch ( KettleException e ) {\n  if ( e.getCause() instanceof java.io.IOException\n       && e.getMessage().equals( \"Error while closing output\" ) ) {\n    // broken pipe: child sqlldr died early — read sqlldr log for root cause\n  }\n}","preventionTips":["Fix any sqlldr startup failures first — they usually precede broken-pipe close errors","Keep transformations running on stable local disk (avoid network FS for log/bad files)","Re-run after confirming the child process survives with the same command line"],"tags":["oracle","sqlldr","ioexception","broken-pipe"],"backgroundTag":"broken-pipe","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"}