{"record":{"id":"256beb152fcb269a","repo":"apache/hadoop","slug":"content-changed","errorCode":null,"errorMessage":"Content changed","messagePattern":"Content changed","errorType":"exception","errorClass":"InvalidPathHandleException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/LocalFileSystemPathHandle.java","lineNumber":59,"sourceCode":"    if (null == bytes) {\n      throw new IOException(\"Missing PathHandle\");\n    }\n    LocalFileSystemPathHandleProto p =\n        LocalFileSystemPathHandleProto.parseFrom(ByteString.copyFrom(bytes));\n    path = p.hasPath()   ? p.getPath()  : null;\n    mtime = p.hasMtime() ? p.getMtime() : null;\n  }\n\n  public String getPath() {\n    return path;\n  }\n\n  public void verify(FileStatus stat) throws InvalidPathHandleException {\n    if (null == stat) {\n      throw new InvalidPathHandleException(\"Could not resolve handle\");\n    }\n    if (mtime != null && mtime != stat.getModificationTime()) {\n      throw new InvalidPathHandleException(\"Content changed\");\n    }\n  }\n\n  @Override\n  public ByteBuffer bytes() {\n    LocalFileSystemPathHandleProto.Builder b =\n        LocalFileSystemPathHandleProto.newBuilder();\n    b.setPath(path);\n    if (mtime != null) {\n      b.setMtime(mtime);\n    }\n    return b.build().toByteString().asReadOnlyByteBuffer();\n  }\n\n  @Override\n  public boolean equals(Object o) {\n    if (this == o) {\n      return true;","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/LocalFileSystemPathHandle.java#L41-L77","documentation":"LocalFileSystemPathHandle optionally captures the file mtime; verify(FileStatus) throws InvalidPathHandleException(\"Content changed\") when a stored mtime exists and differs from the file's current modification time — i.e. the file changed after the handle was created.","triggerScenarios":"Verifying a handle after the target file was overwritten, rewritten, truncated+rewritten, touched, or restored without preserving mtime.","commonSituations":"Concurrent writers finalizing in place, jobs regenerating intermediate files, rsync/tar restores not preserving mtimes, reprocessing pipelines assuming file immutability.","solutions":["Re-capture the handle after content stabilizes and republish it to consumers","Create handles without mtime when strict mtime checking is not wanted","Enforce single-writer discipline: write to temp, atomic rename, then publish handles"],"exampleFix":"// before\nhandle.verify(fs.getFileStatus(p));\n// after\ntry { handle.verify(fs.getFileStatus(p)); }\ncatch (InvalidPathHandleException e) { /* content changed: re-acquire handle or reprocess file */ }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  handle.verify(fs.getFileStatus(p));\n} catch (InvalidPathHandleException e) {\n  // 'Content changed': mtime differs — re-capture the handle or reprocess the file\n}","preventionTips":["Finalize files with atomic rename before publishing handles","Single-writer discipline for handled files","Preserve mtimes when copying/restoring if handles must stay valid"],"tags":["path-handle","mtime","stale-handle","consistency"],"backgroundTag":"stale-file-handle","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}