{"record":{"id":"6c6b1ea8435fd3f2","repo":"pentaho/pentaho-kettle","slug":"tablecompare-exception-unexpectederrorcomparingtables","errorCode":null,"errorMessage":"TableCompare.Exception.UnexpectedErrorComparingTables","messagePattern":"TableCompare\\.Exception\\.UnexpectedErrorComparingTables","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/tablecompare/TableCompare.java","lineNumber":201,"sourceCode":"    Object[] fields = compareTables( getInputRowMeta(), r );\n    Object[] outputRowData = RowDataUtil.addRowData( r, getInputRowMeta().size(), fields );\n    putRow( data.outputRowMeta, outputRowData ); // copy row to output rowset(s);\n    return true;\n  }\n\n  private Object[] compareTables( RowMetaInterface rowMeta, Object[] r ) throws KettleException {\n    try {\n      String referenceSchema = getInputRowMeta().getString( r, data.refSchemaIndex );\n      String referenceTable = getInputRowMeta().getString( r, data.refTableIndex );\n      String compareSchema = getInputRowMeta().getString( r, data.cmpSchemaIndex );\n      String compareTable = getInputRowMeta().getString( r, data.cmpTableIndex );\n      String keyFields = getInputRowMeta().getString( r, data.keyFieldsIndex );\n      String excludeFields = getInputRowMeta().getString( r, data.excludeFieldsIndex );\n\n      return compareTables(\n        rowMeta, r, referenceSchema, referenceTable, compareSchema, compareTable, keyFields, excludeFields );\n    } catch ( Exception e ) {\n      throw new KettleException( BaseMessages.getString(\n        PKG, \"TableCompare.Exception.UnexpectedErrorComparingTables\" ), e );\n    }\n  }\n\n  private Object[] compareTables( RowMetaInterface rowMeta, Object[] r, String referenceSchema,\n    String referenceTable, String compareSchema, String compareTable, String keyFields, String excludeFields ) throws KettleException {\n    long nrErrors = 0L;\n    long nrLeftErrors = 0L;\n    long nrRightErrors = 0L;\n    long nrInnerErrors = 0L;\n    long nrRecordsReference = 0L;\n    long nrRecordsCompare = 0L;\n\n    Object[] result = new Object[6];\n\n    if ( Utils.isEmpty( referenceTable ) ) {\n      Object[] errorRowData = constructErrorRow( rowMeta, r, null, null, null );\n      putError( data.errorRowMeta, errorRowData, 1, BaseMessages.getString(","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/tablecompare/TableCompare.java#L183-L219","documentation":"Generic wrapper exception thrown by the public compareTables(RowMetaInterface, Object[]) helper when any Exception occurs while reading the schema/table/key/exclude field values from the input row and delegating to the private compareTables. It wraps the original cause with the message 'Unexpected error comparing tables'.","triggerScenarios":"Any Exception thrown inside compareTables(rowMeta, r) — e.g. getString() failing on row indices, or the inner private compareTables throwing (SQL errors, missing tables). Called from processRow via the 'fields' local variable assignment at TableCompare.java:183.","commonSituations":"Database connection failures or bad table/schema names during the actual comparison; NPEs when expected row values are missing; the wrapped cause (getCause()) usually carries the real problem — often surfacing as error 2322 from the deeper overload.","solutions":["Inspect the chained cause (KettleException.getCause()) to find the underlying error; the wrapper message itself is not actionable.","Verify the reference/compare schema, table, key fields and exclude fields values in the input row are valid and non-null.","Confirm the database connection works and the referenced tables exist and are readable.","If calling the step API directly (as tests do), populate the input row with all required fields in the expected order."],"exampleFix":"// before\nObject[] fields = compareTables( getInputRowMeta(), r ); // throws opaque wrapper\n// after: guard inputs first\nif ( getInputRowMeta().indexOfValue( \"compare_table\" ) < 0 ) {\n  throw new KettleException( \"compare_table field missing from input row\" );\n}\nObject[] fields = compareTables( getInputRowMeta(), r );","handlingStrategy":"try-catch","validationCode":"// validate all six configured fields resolve in the input row before calling compareTables\nfor ( String f : new String[] { refSchemaField, refTableField, cmpSchemaField, cmpTableField, keyFieldsField, excludeFieldsField } ) {\n  if ( inputRowMeta.indexOfValue( f ) < 0 ) throw new IllegalStateException( \"missing field: \" + f );\n}","typeGuard":null,"tryCatchPattern":"try {\n  Object[] fields = compareTables( getInputRowMeta(), r );\n} catch ( KettleException e ) {\n  Throwable root = e;\n  while ( root.getCause() != null ) root = root.getCause();\n  logError( \"Table comparison failed, root cause: \" + root.getMessage(), root );\n}","preventionTips":["Always inspect getCause() — the wrapper message is generic.","Pre-validate table/schema names in the input rows before running comparisons.","Test DB connectivity with a 'Test connection' before production runs."],"tags":["kettle","wrapped-exception","table-compare","database"],"backgroundTag":"sql-query-failed","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"}