{"record":{"id":"2a761359348b577b","repo":"nodejs/node","slug":"unable-to-get-stats-from-file-s-or-s-n","errorCode":null,"errorMessage":"Unable to get stats from file: %s or %s\\n","messagePattern":"Unable to get stats from file: (.+?) or (.+?)\\\\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"deps/icu-small/source/tools/toolutil/filetools.cpp","lineNumber":127,"sourceCode":"    int32_t result = 0;\n    struct stat stbuf1, stbuf2;\n\n    if (stat(file1, &stbuf1) == 0 && stat(file2, &stbuf2) == 0) {\n        time_t modtime1, modtime2;\n        double diff;\n\n        modtime1 = stbuf1.st_mtime;\n        modtime2 = stbuf2.st_mtime;\n\n        diff = difftime(modtime1, modtime2);\n        if (diff < 0.0) {\n            result = 2;\n        } else if (diff > 0.0) {\n            result = 1;\n        }\n\n    } else {\n        fprintf(stderr, \"Unable to get stats from file: %s or %s\\n\", file1, file2);\n        result = -1;\n    }\n\n    return result;\n}\n\n/* Swap the file separater character given with the new one in the file path. */\nU_CAPI void U_EXPORT2\nswapFileSepChar(char *filePath, const char oldFileSepChar, const char newFileSepChar) {\n    for (int32_t i = 0, length = static_cast<int32_t>(uprv_strlen(filePath)); i < length; i++) {\n        filePath[i] = (filePath[i] == oldFileSepChar ) ? newFileSepChar : filePath[i];\n    }\n}\n","sourceCodeStart":109,"sourceCodeEnd":141,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/icu-small/source/tools/toolutil/filetools.cpp#L109-L141","documentation":"In whichFileModTimeIsLater, the stat() calls for one or both files failed, so their mtimes cannot be compared. The function prints both paths, sets result=-1, and returns -1. Callers treat a negative result as 'cannot determine', typically forcing a rebuild of the target.","triggerScenarios":"stat() fails on file1 or file2 — ENOENT (file missing), EACCES (no traverse permission on a parent dir), ENAMETOOLONG, or ENOTDIR. The else-branch fires whenever the prior stat succeeded check is false.","commonSituations":"Comparing mtimes against a target that has not been generated yet (normal on first build); files on a filesystem that does not support mtime; permission errors on parent directories; symlink loops.","solutions":["Confirm both files exist: ls -l file1 file2.","Check traverse permission on all parent directories of both paths.","If the target legitimately does not exist yet, expect -1 and let the build create it.","Avoid symlink loops or replace broken symlinks."],"exampleFix":"# before: target file does not exist yet\nstat('out.dat') -> ENOENT  -> result -1\n\n# after: normal on first build; build proceeds and creates out.dat\nmake  # regenerates out.dat; subsequent compares succeed","handlingStrategy":"validation","validationCode":"// stat both files first; expect -1 on first build (target absent) but not for permission errors.\n#include <sys/stat.h>\nint canCompareMtimes(const char *a, const char *b) {\n    struct stat sa, sb;\n    if (stat(a, &sa) != 0) return -1;\n    if (stat(b, &sb) != 0) return -1;\n    return 0;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Expect -1 on a first build (no target yet) — it is normal.","Ensure traverse permission on all parent directories.","Avoid broken symlinks and symlink loops.","If -1 persists after the target exists, suspect permissions."],"tags":["icu","toolutil","filetools","build-tool","filesystem","stat"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}