{"record":{"id":"acb194e1a2c6a7b0","repo":"apache/hadoop","slug":"file-is-not-open-for-writing-inode","errorCode":null,"errorMessage":"File is not open for writing: {} (inode {}) {}","messagePattern":"File is not open for writing: (.+?) \\(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":3262,"sourceCode":"        : \"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 + \": \"\n          + leaseExceptionString(src, fileId, holder));\n    }\n    return file;\n  }\n ","sourceCodeStart":3244,"sourceCodeEnd":3280,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java#L3244-L3280","documentation":"checkLease's regular-file case: the file exists but is no longer under construction — it was closed (by close, lease recovery, or another writer) while this client still believed it held the lease. The next addBlock/close on that src fails with LeaseExpiredException('File is not open for writing').","triggerScenarios":"A client's write handle outlives its lease: another client/admin ran recoverLease, hard-limit expiry closed the file, or the file was closed and the same handle kept being used; the next block allocation then fails.","commonSituations":"Long GC pauses or a stalled DFSClient lease-renewer thread so the NN reclaims and closes the lease; automation ran recoverLease on live files; retry logic writing to an already-closed file.","solutions":["Reopen with append() (or re-create) and continue from the last flushed length — the old handle is dead","Fix the root cause: close streams in finally, keep the lease renewer thread healthy, avoid JVM pauses near the lease limits","If another writer legitimately took over, switch to single-writer coordination instead of fighting the lease"],"exampleFix":"// before: stale handle from before the lease was reclaimed\nout.write(buf, 0, n); out.close();   // LeaseExpiredException\n// after\nlong len = fs.getFileStatus(path).getLen();\ntry (FSDataOutputStream out = ((DistributedFileSystem) fs).append(path)) {\n  /* re-append everything beyond len */\n}","handlingStrategy":"try-catch","validationCode":"if (!((DistributedFileSystem) fs).isFileClosed(path)) {\n  // still open (by us or someone else); if not by us, expect lease contention\n}","typeGuard":null,"tryCatchPattern":"catch (LeaseExpiredException e) { if (e.getMessage() != null && e.getMessage().contains(\"not open for writing\")) { long len = fs.getFileStatus(src).getLen(); reopenAppendAndContinueFrom(len); } else throw e; }","preventionTips":["Close FSDataOutputStream in finally; never cache write handles across long pauses","Monitor DFSClient 'Failed to renew lease' warnings and fail fast","Keep writer JVM GC pauses well under the soft limit (default 60s)"],"tags":["hdfs","lease-expired","append","lease-renewal"],"backgroundTag":"lease-expired","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}