{"record":{"id":"28d58f5dbbe6b4d5","repo":"pentaho/pentaho-kettle","slug":"no-control-file-specified","errorCode":null,"errorMessage":"No control file specified","messagePattern":"No control file specified","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"plugins/gp-bulk-loader/core/src/main/java/org/pentaho/di/trans/steps/gpbulkloader/GPBulkLoader.java","lineNumber":337,"sourceCode":"        throw new KettleException( \"Error retrieving sqlldr string\", ex );\n      }\n    } else {\n      throw new KettleException( \"No psql application specified\" );\n    }\n\n    if ( meta.getControlFile() != null ) {\n      try {\n        FileObject fileObject =\n          KettleVFS.getInstance( getTransMeta().getBowl() )\n            .getFileObject( environmentSubstitute( meta.getControlFile() ), getTransMeta() );\n\n        sb.append( \" -n -f \" );\n        sb.append( enclosure ).append( KettleVFS.getFilename( fileObject ) ).append( enclosure );\n      } catch ( Exception ex ) {\n        throw new KettleException( \"Error retrieving controlfile string\", ex );\n      }\n    } else {\n      throw new KettleException( \"No control file specified\" );\n    }\n\n    if ( meta.getLogFile() != null ) {\n      try {\n        FileObject fileObject =\n          KettleVFS.getInstance( getTransMeta().getBowl() )\n            .getFileObject( environmentSubstitute( meta.getLogFile() ), getTransMeta() );\n\n        sb.append( \" -o \" );\n        sb.append( enclosure ).append( KettleVFS.getFilename( fileObject ) ).append( enclosure );\n      } catch ( Exception ex ) {\n        throw new KettleException( \"Error retrieving logfile string\", ex );\n      }\n    }\n\n    DatabaseMeta dm = meta.getDatabaseMeta();\n    if ( dm != null ) {\n      String user = Const.NVL( dm.getUsername(), \"\" );","sourceCodeStart":319,"sourceCodeEnd":355,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/plugins/gp-bulk-loader/core/src/main/java/org/pentaho/di/trans/steps/gpbulkloader/GPBulkLoader.java#L319-L355","documentation":"createCommandLine() demands a control file for the gpload/psql invocation. When meta.getControlFile() is null the step throws this KettleException, because psql cannot run the bulk load without the '-f <controlfile>' argument. It is a required-field validation error.","triggerScenarios":"execute() -> createCommandLine() runs while meta.getControlFile() is null: the control file field in the GP Bulk Loader step was left empty, or the metadata was loaded from XML missing that attribute.","commonSituations":"Step configured without generating/filling the control file path; transformation XML hand-edited or from an older schema lacking the controlFile element; programmatic GPBulkLoaderMeta usage without setControlFile(); user assumed the plugin would generate the control file automatically.","solutions":["Set the control file path in the GP Bulk Loader step dialog (a valid gpload control file).","If building metadata in code, call meta.setControlFile(\"/path/to/load.ctl\") before execute().","Re-save the step/transformation with a current plugin version so the controlFile attribute is written to XML.","Pre-validate the meta in your orchestration code and fail with a descriptive message before the transformation runs."],"exampleFix":"// before\nGPBulkLoaderMeta meta = new GPBulkLoaderMeta();\nmeta.setPsqlpath(\"/usr/bin/psql\");\n// controlFile never set -> throws\n\n// after\nmeta.setControlFile(\"/opt/gp/control/load.ctl\");","handlingStrategy":"validation","validationCode":"if (meta.getControlFile() == null || meta.getControlFile().trim().isEmpty()) {\n  throw new IllegalArgumentException(\n    \"GP Bulk Loader: control file path is required before execute()\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  execute(meta, wait);\n} catch (KettleException e) {\n  if (e.getMessage().contains(\"No control file specified\")) {\n    meta.setControlFile(generateControlFile());\n    execute(meta, wait);\n  } else throw e;\n}","preventionTips":["Generate the gpload control file as part of the ETL pipeline setup","Never hand-edit the step XML - configure via Spoon so controlFile is persisted","Add a pre-run metadata check that asserts psqlpath, controlFile, and connection are all set"],"tags":["missing-config","control-file","required-field","kettle"],"backgroundTag":"missing-required-config-field","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"}