{"record":{"id":"1cab950e250dd1c8","repo":"apache/hadoop","slug":"inode-is-not-a-regular-file-inode","errorCode":null,"errorMessage":"INode is not a regular file: {} (inode {}) {}","messagePattern":"INode is not a regular file: (.+?) \\(inode (.+?)\\) (.+?)","errorType":"exception","errorClass":"LeaseExpiredException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java","lineNumber":3257,"sourceCode":"  }\n\n  private String leaseExceptionString(String src, long fileId, String holder) {\n    final Lease lease = leaseManager.getLease(holder);\n    return src + \" (inode \" + fileId + \") \" + (lease != null? lease.toString()\n        : \"Holder \" + holder + \" does not have any open files.\");\n  }\n\n  INodeFile checkLease(INodesInPath iip, String holder, long fileId)\n      throws LeaseExpiredException, FileNotFoundException {\n    String src = iip.getPath();\n    INode inode = iip.getLastINode();\n    assert hasReadLock(RwLockMode.FS);\n    if (inode == null) {\n      throw new FileNotFoundException(\"File does not exist: \"\n          + leaseExceptionString(src, fileId, holder));\n    }\n    if (!inode.isFile()) {\n      throw new LeaseExpiredException(\"INode is not a regular file: \"\n          + leaseExceptionString(src, fileId, holder));\n    }\n    final INodeFile file = inode.asFile();\n    if (!file.isUnderConstruction()) {\n      throw new LeaseExpiredException(\"File is not open for writing: \"\n          + leaseExceptionString(src, fileId, holder));\n    }\n    // No further modification is allowed on a deleted file.\n    // A file is considered deleted, if it is not in the inodeMap or is marked\n    // as deleted in the snapshot feature.\n    if (isFileDeleted(file)) {\n      throw new FileNotFoundException(\"File is deleted: \"\n          + leaseExceptionString(src, fileId, holder));\n    }\n    final String owner = file.getFileUnderConstructionFeature().getClientName();\n    if (holder != null && !owner.equals(holder)) {\n      throw new LeaseExpiredException(\"Client (=\" + holder\n          + \") is not the lease owner (=\" + owner + \": \"","sourceCodeStart":3239,"sourceCodeEnd":3275,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java#L3239-L3275","documentation":"checkLease found that the resolved last INode is not a regular file (a directory or symlink). A write lease only applies to files, so the caller gets LeaseExpiredException('INode is not a regular file: ...') with path, inode id, and holder context.","triggerScenarios":"addBlock/close/append-family calls with a src that resolves to a directory — the writer's file was deleted and the path re-created as a directory, or the path string always was a directory path used as a file target.","commonSituations":"Path template bugs that append a filename to a path which itself names a directory; another job replaced the file with a same-named directory; snapshot restore changed the inode type under an active writer.","solutions":["Write to a file path under the directory (parent + filename), never the directory itself","If the path was hijacked, pick a new output path and restart the write","Type-check the target with getFileStatus().isFile() before starting long writes"],"exampleFix":"// before\nFSDataOutputStream out = fs.create(dirPath);   // dirPath is a directory -> LeaseExpiredException\n// after\nFSDataOutputStream out = fs.create(new Path(dirPath, \"part-0000\"));","handlingStrategy":"validation","validationCode":"FileStatus st = fs.getFileStatus(p);\nif (!st.isFile()) throw new IllegalArgumentException(\"not a regular file: \" + p);","typeGuard":"static boolean isRegularFile(FileSystem fs, Path p) throws IOException {\n  try { return fs.getFileStatus(p).isFile(); }\n  catch (FileNotFoundException e) { return false; }\n}","tryCatchPattern":"catch (LeaseExpiredException e) { if (e.getMessage() != null && e.getMessage().contains(\"not a regular file\")) failWithBadPathHint(); else throw e; }","preventionTips":["Derive file paths explicitly as parent directory + filename","Type-check paths that come from config or user input before long writes"],"tags":["hdfs","lease","not-a-file","path-misuse"],"backgroundTag":"path-is-not-a-regular-file","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}