pentaho/pentaho-kettle · error · KettleException
DynamicSQLRow.Exception.IncorrectNrTemplateFields
Error message
DynamicSQLRow.Exception.IncorrectNrTemplateFields
What it means
DynamicSQLRow.lookupValues validates that the number of template fields (addMeta, the fields the SQL is expected to return) matches the number of columns the step actually appends to the output row (outputRowMeta size minus input size). If these counts differ, it throws this KettleException naming both counts and the SQL.
Solutions
- Reopen the Dynamic SQL Row step, re-detect the query fields so output fields match the SQL
- Verify the SQL template column count is stable across variable substitution
- Clear any cached query-field metadata and re-save the transformation
- Align the declared output fields in the dialog with the actual SELECT list
Example fix
// before SELECT id, name FROM customers WHERE region = ? // dialog still declares 3 return fields // after SELECT id, name, created_at FROM customers WHERE region = ? // now matches the 3 declared fields
Defensive patterns
Strategy: validation
Validate before calling
// In the step dialog, click 'SQL' to re-detect fields after any SQL change,
// then verify counts match:
int declaredOutputFields = outputRowMeta.size() - inputRowMeta.size();
if (declaredOutputFields != templateFields.size()) {
throw new IllegalStateException("Template/output field count mismatch: " + declaredOutputFields + " vs " + templateFields.size());
} Try / catch
try {
return lookupValues(inputRowMeta, row);
} catch (KettleException e) {
logError("Template field count mismatch — re-detect SQL fields in the dialog", e);
throw e;
} Prevention
- Re-run field detection in the step dialog after every SQL edit
- Avoid SQL templates whose column count varies with variable values
- Clear cached query fields when switching databases/drivers
- Preview the step after changes to catch mismatches at design time
When it happens
Trigger: At runtime in processRow→lookupValues when the template row metadata (addMeta from getQueryFields) has a different field count than the declared output row metadata — e.g. the SQL was edited after the step metadata was generated, or 'replace variables' changed the query.
Common situations: Editing the dynamic SQL template without re-running 'SQL' detection in the step dialog; environment variable substitution producing a different column count per run; cached QueryFields from an older SQL.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- DatabaseJoinMeta.Exception.UnableToDetermineQueryFields +…
- SQLFileOutputMeta.Exception.ErrorGettingFields
- SQLFileOutputMeta.Exception.TableNotFound
- BaseStreamStepMeta.CheckResult.ResultStepMissing
- CheckSum.Error.UnknownEvaluationMethod
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/bccf4989b10aa780.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/trans/steps/dynamicsqlrow/DynamicSQLRow.java:122
}
} else {
if ( meta.isQueryOnlyOnChange() ) {
data.previousrowbuffer.clear();
}
// Set the values on the prepared statement (for faster exec.)
ResultSet rs = data.db.openQuery( sql );
// Get a row from the database...
Object[] add = data.db.getRow( rs );
RowMetaInterface addMeta = data.db.getReturnRowMeta();
// Also validate the data types to make sure we've not place an incorrect template in the dialog...
//
if ( add != null ) {
int nrTemplateFields = data.outputRowMeta.size() - getInputRowMeta().size();
if ( addMeta.size() != nrTemplateFields ) {
throw new KettleException( BaseMessages.getString(
PKG, "DynamicSQLRow.Exception.IncorrectNrTemplateFields", nrTemplateFields, addMeta.size(), sql ) );
}
StringBuilder typeErrors = new StringBuilder();
for ( int i = 0; i < addMeta.size(); i++ ) {
ValueMetaInterface templateValueMeta = addMeta.getValueMeta( i );
ValueMetaInterface outputValueMeta = data.outputRowMeta.getValueMeta( getInputRowMeta().size() + i );
if ( templateValueMeta.getType() != outputValueMeta.getType() ) {
if ( typeErrors.length() > 0 ) {
typeErrors.append( Const.CR );
}
typeErrors.append( BaseMessages.getString(
PKG, "DynamicSQLRow.Exception.TemplateReturnDataTypeError", templateValueMeta.toString(),
outputValueMeta.toString() ) );
}
}
if ( typeErrors.length() > 0 ) {
throw new KettleException( typeErrors.toString() );View on GitHub (pinned to f3058517a1)