{"record":{"id":"725210a221325417","repo":"pentaho/pentaho-kettle","slug":"processfiles-error-targetfilenotfile","errorCode":null,"errorMessage":"ProcessFiles.Error.TargetFileNotFile","messagePattern":"ProcessFiles\\.Error\\.TargetFileNotFile","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/processfiles/ProcessFiles.java","lineNumber":137,"sourceCode":"      }\n      String targetFilename = null;\n      if ( meta.getOperationType() != ProcessFilesMeta.OPERATION_TYPE_DELETE ) {\n        // get value for target filename\n        targetFilename = getInputRowMeta().getString( r, data.indexOfTargetFilename );\n\n        if ( Utils.isEmpty( targetFilename ) ) {\n          logError( BaseMessages.getString( PKG, \"ProcessFiles.Error.TargetFileEmpty\" ) );\n          throw new KettleException( BaseMessages.getString( PKG, \"ProcessFiles.Error.TargetFileEmpty\" ) );\n        }\n        data.targetFile = KettleVFS.getInstance( getTransMeta().getBowl() ).getFileObject( targetFilename, getTransMeta() );\n        if ( data.targetFile.exists() ) {\n          if ( log.isDetailed() ) {\n            logDetailed( BaseMessages.getString( PKG, \"ProcessFiles.Log.TargetFileExists\", targetFilename ) );\n          }\n          // check if target is really a file otherwise it could overwrite a complete folder by copy or move operations\n          if ( data.targetFile.getType() != FileType.FILE ) {\n            logError( BaseMessages.getString( PKG, \"ProcessFiles.Error.TargetFileNotFile\", targetFilename ) );\n            throw new KettleException( BaseMessages.getString(\n              PKG, \"ProcessFiles.Error.TargetFileNotFile\", targetFilename ) );\n          }\n\n        } else {\n          // let's check parent folder\n          FileObject parentFolder = data.targetFile.getParent();\n          if ( !parentFolder.exists() ) {\n            if ( !meta.isCreateParentFolder() ) {\n              throw new KettleException( BaseMessages.getString(\n                PKG, \"ProcessFiles.Error.TargetParentFolderNotExists\", parentFolder.toString() ) );\n            } else {\n              parentFolder.createFolder();\n            }\n          }\n          if ( parentFolder != null ) {\n            parentFolder.close();\n          }\n        }","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/processfiles/ProcessFiles.java#L119-L155","documentation":"Thrown when the target path exists but is not a regular file (e.g. it is a folder). This guard prevents copy/move operations from overwriting an entire folder with a file, which would corrupt the destination directory.","triggerScenarios":"Operation Copy/Move; data.targetFile.exists() is true and data.targetFile.getType() != FileType.FILE.","commonSituations":"Target filename computed to a directory path by mistake (e.g. missing filename part in concatenation); user intended to move into a folder but gave the folder as the destination instead of folder + name; leftover directory at target location from previous runs.","solutions":["Correct the target filename expression to include the file name, not just the folder (e.g. /out/dir/file.txt instead of /out/dir).","Remove or rename the conflicting directory at the target path.","Use step error handling to catch rows whose target collides with a directory and route them elsewhere.","Compute target path as concat(targetFolder, \"/\", baseName(source)) so a folder-only value can never occur."],"exampleFix":"// before\ntarget = \"/data/output/archive\" // a directory\n// after\ntarget = \"/data/output/archive/\" concat basename(sourceFilename)","handlingStrategy":"validation","validationCode":"// Guard: target must be a file path, and if it exists it must not be a directory\njava.io.File t = new java.io.File(targetFilename);\nboolean safe = !t.exists() || t.isFile();","typeGuard":"boolean safeTargetPath(String path) {\n  java.io.File f = (path == null) ? null : new java.io.File(path);\n  return f != null && (!f.exists() || f.isFile());\n}","tryCatchPattern":"try {\n  processRow();\n} catch (KettleException e) {\n  if (e.getMessage().contains(\"TargetFileNotFile\")) {\n    logError(\"Target points to a directory: \" + extractPath(e));\n  } else throw e;\n}","preventionTips":["Always append the file name to the target folder in your path expression","Clean stale directories from the target location before runs","Validate computed target paths with a File Exists/preview step","Avoid using user-supplied folder paths directly as full target paths"],"tags":["pdi","kettle","path-is-directory","overwrite-protection"],"backgroundTag":"path-is-not-a-directory","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"}