{"record":{"id":"a1ec61fcff8142fa","repo":"pentaho/pentaho-kettle","slug":"zipfile-error-sourcefilenotfile","errorCode":null,"errorMessage":"ZipFile.Error.SourceFileNotFile","messagePattern":"ZipFile\\.Error\\.SourceFileNotFile","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/trans/steps/zipfile/ZipFile.java","lineNumber":163,"sourceCode":"        log.logError( toString(), BaseMessages.getString( PKG, \"ZipFile.Error.SourceFileEmpty\" ) );\n        throw new KettleException( BaseMessages.getString( PKG, \"ZipFile.Error.SourceFileEmpty\" ) );\n      }\n      data.sourceFile = KettleVFS.getInstance( getTransMeta().getBowl() )\n        .getFileObject( sourceFilename, this );\n\n      // Check sourcefile\n      boolean skip = false;\n      if ( !data.sourceFile.exists() ) {\n        log\n          .logError( toString(), BaseMessages\n            .getString( PKG, \"ZipFile.Error.SourceFileNotExist\", sourceFilename ) );\n        throw new KettleException( BaseMessages\n          .getString( PKG, \"ZipFile.Error.SourceFileNotExist\", sourceFilename ) );\n      } else {\n        if ( data.sourceFile.getType() != FileType.FILE ) {\n          log.logError( toString(), BaseMessages\n            .getString( PKG, \"ZipFile.Error.SourceFileNotFile\", sourceFilename ) );\n          throw new KettleException( BaseMessages.getString(\n            PKG, \"ZipFile.Error.SourceFileNotFile\", sourceFilename ) );\n        }\n      }\n\n      // get basefolder\n      if ( data.indexOfBaseFolder > -1 ) {\n        data.baseFolder = getInputRowMeta().getString( r, data.indexOfBaseFolder );\n      }\n\n      // get destination folder\n      String moveToFolder = null;\n      if ( data.indexOfMoveToFolder > -1 ) {\n        moveToFolder = getInputRowMeta().getString( r, data.indexOfMoveToFolder );\n        if ( Utils.isEmpty( moveToFolder ) ) {\n          throw new KettleException( BaseMessages.getString( PKG, \"ZipFile.Error.EmptyMoveToFolder\" ) );\n        }\n      }\n","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/steps/zipfile/ZipFile.java#L145-L181","documentation":"Source-file validation in ZipFile.processRow: the configured source file exists but is not a regular file (it is a directory or special file), so it cannot be zipped. This fires after the existence check passed but the type check failed.","triggerScenarios":"data.sourceFile.exists() is true but data.sourceFile.getType() != FileType.FILE at ZipFile.java:163, i.e., the path resolves to a directory.","commonSituations":"User pointed the source filename field at a directory expecting the step to zip the whole folder; a glob or prefix match produced a directory path; dynamic filename construction lost the file extension/name portion.","solutions":["Point the source filename field at individual files, not the containing directory.","Use a 'Get File Names' step with a wildcard filter to enumerate files, then feed each into ZipFile.","Fix dynamic filename construction so the file name (not just the folder) is included.","Add a validation step that checks the path is a file before zipping."],"exampleFix":"// before\nsourceFilename = \"/data/exports\";            // directory\n// after\nsourceFilename = \"/data/exports/report.csv\"; // actual file","handlingStrategy":"validation","validationCode":"// Before zipping, ensure the path is a regular file\nFile f = new File(sourceFilename);\nif (f.exists() && f.isDirectory()) {\n  throw new IllegalArgumentException(\"ZipFile source must be a file, not a directory: \" + sourceFilename);\n}","typeGuard":null,"tryCatchPattern":"try {\n  transformation.execute();\n} catch (KettleException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"SourceFileNotFile\")) {\n    log.error(\"ZipFile source path is a directory - point to individual files\", e);\n  } else { throw e; }\n}","preventionTips":["Enumerate files with a 'Get File Names' step before zipping instead of passing folders.","Keep the file name (not just the directory) in dynamically built paths.","Add an is-file check step upstream."],"tags":["pdi","kettle","filesystem","zip","path"],"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"}