Skip to content

zone.js timer patch throws when native timer returns null #70044

Closed

Description

@ParryQiu

Which @angular/* package(s) are the source of the bug?

zone.js

Is this a regression?

No. The same unguarded access exists in zone.js 0.14.10 and in the current main implementation.

Description

patchTimer() assumes that a non-numeric return value from the native timer is an object. If an injected browser policy, extension, test harness, or automation wrapper blocks a timer and returns null, zone.js reads handleOrId.refresh and throws:

TypeError: Cannot read properties of null (reading 'refresh')

The current source assigns data.handle = handleOrId and then calls isFunction(handleOrId.refresh) without checking that handleOrId is non-null.

Minimal reproduction

<!doctype html>
<script>
  const nativeSetTimeout = window.setTimeout;
  window.setTimeout = function (callback, delay, ...args) {
    if (delay >= 30000) return null;
    return nativeSetTimeout(callback, delay, ...args);
  };
</script>
<script src="https://unpkg.com/zone.js@0.14.10/bundles/zone.umd.js"></script>
<script>
  setTimeout(() => {}, 30000);
</script>

Expected behavior

zone.js should not dereference a null timer handle. A nullish guard around refresh detection would preserve the existing numeric and Node.js handle behavior, for example by treating a nullish handle as non-refreshable.

Actual behavior

The call throws synchronously from patchTimer.scheduleTask() while reading .refresh.

Environment

  • zone.js: 0.14.10
  • Browser case observed with an injected timer blocker returning null
  • Also reproducible with the standalone wrapper above

Additional context

We observed both setTimeout(30000) and setInterval(86400000) variants. This is an interoperability boundary: browsers normally return numeric timer IDs, but wrappers that intentionally block long timers can return null. Application-side filtering can suppress duplicate telemetry, but the underlying null dereference remains in zone.js.

Activity

  1. added this to the needsTriage milestone on Aug 1, 2026
  2. added this to the needsTriage milestone on Aug 1, 2026
  3. added a commit that references this issue on Aug 3, 2026
    36c2197
  4. angular-automatic-lock-bot commented on Oct 19, 2026

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  5. locked and limited conversation to collaborators on Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: zonesIssues related to zone.js

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions