{"record":{"id":"b3f22796d6814fdc","repo":"pentaho/pentaho-kettle","slug":"synchronizeaftermerge-exception-keycouldnotfound","errorCode":"SynchronizeAfterMerge.Exception.KeyCouldNotFound","errorMessage":"SynchronizeAfterMerge.Exception.KeyCouldNotFound","messagePattern":"SynchronizeAfterMerge\\.Exception\\.KeyCouldNotFound","errorType":"exception","errorClass":"KettleDatabaseException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/synchronizeaftermerge/SynchronizeAfterMerge.java","lineNumber":200,"sourceCode":"          incrementLinesInput();\n\n          if ( add == null ) {\n            // nothing was found:\n\n            if ( data.stringErrorKeyNotFound == null ) {\n              data.stringErrorKeyNotFound =\n                BaseMessages.getString( PKG, \"SynchronizeAfterMerge.Exception.KeyCouldNotFound\" )\n                  + data.lookupParameterRowMeta.getString( lookupRow );\n              data.stringFieldnames = \"\";\n              for (int i = 0; i < data.lookupParameterRowMeta.size(); i++) {\n                if ( i > 0 ) {\n                  data.stringFieldnames += \", \";\n                }\n                data.stringFieldnames += data.lookupParameterRowMeta.getValueMeta( i ).getName();\n              }\n            }\n            data.lookupFailure = true;\n            throw new KettleDatabaseException( BaseMessages.getString( PKG,\n              \"SynchronizeAfterMerge.Exception.KeyCouldNotFound\", data.lookupParameterRowMeta.getString(\n                lookupRow ) ) );\n          } else {\n            if ( log.isRowLevel() ) {\n              logRowlevel( BaseMessages.getString( PKG, \"SynchronizeAfterMerge.Log.FoundRowForUpdate\",\n                data.insertRowMeta.getString( row ) ) );\n            }\n\n            for (int i = 0; i < data.valuenrs.length; i++) {\n              if ( meta.getUpdate()[i].booleanValue() ) {\n                ValueMetaInterface valueMeta = data.inputRowMeta.getValueMeta( data.valuenrs[i] );\n                ValueMetaInterface retMeta = data.db.getReturnRowMeta().getValueMeta( i );\n\n                Object rowvalue = row[data.valuenrs[i]];\n                Object retvalue = add[i];\n\n                if ( valueMeta.compare( rowvalue, retMeta, retvalue ) != 0 ) {\n                  updateorDelete = true;","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/synchronizeaftermerge/SynchronizeAfterMerge.java#L182-L218","documentation":"Thrown in lookupValues() when the step executes the lookup SELECT for the key lookup (used to decide update vs insert) and no matching row is returned, while the operation is update/delete. data.lookupFailure is set and a KettleDatabaseException with the lookup key values is raised, because the step cannot perform an update/delete on a record that does not exist.","triggerScenarios":"performUpdate or performDelete is true; the db lookup query built from the configured key/lookup fields returns an empty ResultSet; the code enters the 'else' branch for update/delete without a found row and throws.","commonSituations":"Key values differ in type or padding (trailing spaces, CHAR vs VARCHAR) between source and target; case-sensitive comparison; key column values truncated; lookup keys misconfigured in the dialog; row was deleted by a concurrent process.","solutions":["Verify the key field mappings (table field <-> stream field) in the step's 'Lookup keys' grid match the real target table columns.","Normalize data types/whitespace of key values upstream (Trim strings, type conversions) so the lookup SELECT matches.","Route such rows through a different path: use the step's error handling or filter, or change operation to 'insert' for missing keys.","Enable the step's error handling (isDoingErrorHandling) so lookup failures go to the error stream instead of failing the transformation."],"exampleFix":"// before: key column CHAR(10) padded, lookup compares unpadded value\nSELECT ... WHERE code = ?\n// after: trim upstream before the step\nRTrim(code) AS code FROM source;","handlingStrategy":"try-catch","validationCode":"// Validate key existence before choosing update/delete\nboolean keyExists = lookupKeyInTarget(keyValues); // SELECT 1 FROM target WHERE key = ?\nif (!keyExists && operation.equals(\"update\")) {\n  throw new ValidationException(\"Update requested but key not found: \" + Arrays.toString(keyValues));\n}","typeGuard":null,"tryCatchPattern":"catch (KettleDatabaseException e) {\n  if (e.getMessage().contains(\"KeyCouldNotFound\")) {\n    // route row to insert path or error stream\n  } else { throw e; }\n}","preventionTips":["Trim and type-cast key fields upstream so lookups match (CHAR padding, case).","Double-check the key field mapping grid against real target columns.","Enable step error handling so lookup misses go to an error stream."],"tags":["database","key-lookup","pentaho-kettle"],"backgroundTag":"record-not-found","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"}