Skip to content

fs: preserve negative utimes timestamps - #66634

Open
guybedford wants to merge 2 commits into
nodejs:mainfrom
guybedford:fs-negative-utimes
Open

guybedford wants to merge 2 commits into
nodejs:mainfrom
guybedford:fs-negative-utimes

Conversation

@guybedford

Copy link
Copy Markdown
Contributor

This is the semver-major alternative to #64627, fixes #64597.

toUnixTimestamp() silently replaced negative numeric timestamps with the current time, while negative strings and Dates were passed through as pre-epoch times:

fs.utimesSync(p, -1, -1);              // mtime = now
fs.utimesSync(p, '-1', '-1');          // mtime = 1969-12-31T23:59:59Z
fs.utimesSync(p, new Date(-1000), ...) // mtime = 1969-12-31T23:59:59Z

Removing the clamp exposed that Windows reinterprets stat tv_sec as unsigned long, so that pre-epoch times read back as post-2038 times (via static_cast<unsigned long> in FillStatsArray). This was a Node.js decision from #43714 to work around libuv's 32-bit long tv_sec on Windows, which is what the test-fs-utimes-y2K38.js Windows overflow_mtime case covered. As discussed in #64627, this PR treats negative times as pre-epoch on all platforms, consistent with POSIX:

  • toUnixTimestamp() no longer replaces negative numbers with the current time.
  • Windows stat times are no longer cast to unsigned, so negative values are pre-epoch times rather than post-2038 times. As a result, times after 2038-01-19T03:14:07Z are no longer representable on Windows until libuv gains 64-bit time support.
  • Docs updated for the atime / mtime rules and the Windows time range.

Test changes:

  • test-fs-utimes.js now computes the expected mtime independently of fs._toUnixTimestamp() (previously the oracle was the code under test, so the negative case always passed), uses an absolute difference, and adds negative number and pre-epoch Date cases. These are skipped on AIX, which rejects pre-epoch times with EINVAL.
  • test-fs-utimes-y2K38.js skips the Y2K38 round trip on Windows and drops the overflow_mtime case, keeping the Windows precision check.

A CITGM run is suggested per the discussion in #64627.

`toUnixTimestamp()` silently replaced negative numeric timestamps with
the current time, while negative strings and Dates were passed through
as pre-epoch times.

On Windows, stat times were additionally reinterpreted as unsigned so
that pre-epoch times read back as post-2038 times. Treat negative times
as pre-epoch on all platforms, consistent with POSIX, at the cost of
post-2038 times on Windows which libuv is unable to represent.

Fixes: nodejs#64597
Refs: nodejs#64627
Assisted-by: OpenCode
Signed-off-by: Guy Bedford <guybedford@gmail.com>
@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. fs Issues and PRs related to file-system APIs and the fs module. needs-ci PRs that need a full CI run. labels Oct 10, 2026
@codecov

codecov Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.51%. Comparing base (ae5a0f4) to head (cd1a005).
⚠️ Report is 146 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #66634      +/-   ##
==========================================
- Coverage   92.78%   90.51%   -2.28%     
==========================================
  Files         422      797     +375     
  Lines      193692   278189   +84497     
  Branches    29881    53458   +23577     
==========================================
+ Hits       179718   251801   +72083     
- Misses      13645    16766    +3121     
- Partials      329     9622    +9293     
Files with missing lines Coverage Δ
lib/internal/fs/utils.js 96.28% <ø> (+4.83%) ⬆️
src/node_file-inl.h 85.91% <ø> (ø)

... and 537 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@richardlau richardlau added the semver-major PRs that contain breaking changes and should be released in the next major version. label Oct 10, 2026
@guybedford guybedford added the request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. label Oct 17, 2026
@guybedford

Copy link
Copy Markdown
Contributor Author

@aduh95 would value your review on this one given it's a major change. Otherwise another @nodejs/tsc review would be appreciated.

@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. label Oct 17, 2026
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

@LiviaMedeiros LiviaMedeiros left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with changelog entries added to the docs.

CITGM: https://ci.nodejs.org/view/Node.js-citgm/job/citgm-smoker/3798/

Comment thread doc/api/fs.md
Assisted-by: Claude Code
Signed-off-by: Guy Bedford <guybedford@gmail.com>
@guybedford

Copy link
Copy Markdown
Contributor Author

CITGM failures seem unrelated to this change - seems like the suite might not be passing on main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Issues and PRs that require attention from people who are familiar with C++. fs Issues and PRs related to file-system APIs and the fs module. needs-ci PRs that need a full CI run. semver-major PRs that contain breaking changes and should be released in the next major version.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fs: incorrect handling of numeric times from before the unix epoch

5 participants