Date: 2026-07-07
Bug ID: TypeError: Cannot read properties of null (reading 'nodeType')
Location: common.js:220 in function Узел (Node)
Severity: CRITICAL — Causes immediate player crash
ROOT CAUSE: Commit ebf05b5 changed HTML element IDs from Russian to English in player.html, but player.js still references the OLD Russian IDs. When document.getElementById() is called with a Russian ID that no longer exists in the DOM, it returns null, which then crashes when the code tries to access .nodeType on line 220 of common.js.
IMPACT: Complete player failure. Statistics overlay cannot be populated, causing a JavaScript exception that halts execution.
commit ebf05b5121b9643cf4f75a4e6caee7a5fceb6def
Author: Claude Sonnet 4.5 <claude@maton.ai>
Date: Tue Jul 7 02:58:32 2026 +0000
Replace all Russian tooltip text with English in statistics overlay
All user-visible tooltip text in the statistics overlay panel (opened with
the 'S' key) has been replaced with English translations. Russian tooltips
are now commented out and English versions are active.
BEFORE (Russian IDs active):
<span id=статистика-сжатиевидео title="Параметры сжатия видео..."></span>
<!-- <span id=statistics-videocompression title="Video compression parameters..."></span> -->AFTER (English IDs active):
<!-- <span id=статистика-сжатиевидео title="Параметры сжатия видео..."></span> -->
<span id=statistics-videocompression title="Video compression parameters..."></span>The commit activated the English ID and commented out the Russian ID.
The following IDs were changed from Russian → English in player.html:
| Old Russian ID | New English ID | Line Reference |
|---|---|---|
статистика-сжатиевидео |
statistics-videocompression |
Line 68 |
статистика-сервер |
statistics-server |
Line 90 |
статистика-интервалобновления |
statistics-updateinterval |
Line 136 |
статистика-сегментовдобавлено |
statistics-segmentsadded |
Line 142 |
статистика-секунддобавлено |
statistics-secondsadded |
Line 146 |
статистика-толщинасегмента |
statistics-segmentthickness |
Line 164 |
статистика-толщинаканала |
statistics-channelthickness |
Line 169 |
статистика-ожиданиеответа |
statistics-responsewait |
Line 177 |
статистика-непросмотрено |
statistics-unwatched |
Line 195 |
All 9 IDs were switched in the same commit without updating player.js.
-
player.js line 1846 or line 2000:
Узел("статистика-сжатиевидео").textContent
-
common.js line 218 (
Узелfunction):const элЭлемент = typeof пЭлемент == 'string' ? document.getElementById(пЭлемент) // ← Returns NULL because ID doesn't exist : пЭлемент;
-
common.js line 220 (crash site):
Проверить(элЭлемент.nodeType === 1); // ← TypeError: Cannot read 'nodeType' of null
player.jscallsУзел("статистика-сжатиевидео")player.htmlnow contains<span id=statistics-videocompression>(English)- The Russian ID
статистика-сжатиевидеоno longer exists in the DOM document.getElementById("статистика-сжатиевидео")returnsnull- The assertion
элЭлемент.nodeType === 1tries to access.nodeTypeonnull→ CRASH
ПараметрыВидео:
Узел("статистика-разрешениевидео").textContent +
" " +
Узел("статистика-сжатиевидео").textContent, // ← CRASH HEREContext: This is inside a data-gathering function that creates a report object with video parameters.
Function: Appears to be part of a statistics reporting or feedback submission feature.
if (оДанные.чЧастотаКадров) {
сСжатиеВидео += ` ${оДанные.чЧастотаКадров < 0 ? "≈" : ""
}${Math.abs(оДанные.чЧастотаКадров).toFixed(2)} ${Текст("J0140")}`;
}
Узел("статистика-сжатиевидео").textContent = сСжатиеВидео; // ← CRASH HEREContext: This is the main statistics display update logic. It runs every time the statistics overlay is refreshed (typically when new video metadata arrives from the worker).
Function: This populates the "Video Compression" field in the statistics overlay with:
- Codec standard (H.264, HEVC, etc.)
- Profile and level
- Reference frames
- Color range
- Frame rate
Frequency: Called repeatedly during playback whenever video metadata changes.
} else {
Узел("статистика-сжатиевидео").textContent = "—"; // ← CRASH HERE
Узел("статистика-разрешениевидeo").textContent = "—";
}Context: This is the fallback/reset branch when video metadata is unavailable (e.g., during stream buffering, initialization, or errors).
Function: Sets the video compression field to the placeholder "—" (em dash) to indicate "no data available."
Frequency: Called whenever the player state is reset or when transitioning between streams.
Based on the commit changes, the following Russian IDs are also broken in player.js:
| Russian ID in player.js | Was Changed To | Crash Location |
|---|---|---|
статистика-сервер |
statistics-server |
Multiple locations |
статистика-интервалобновления |
statistics-updateinterval |
Statistics update |
статистика-сегментовдобавлено |
statistics-segmentsadded |
Statistics update |
статистика-секунддобавлено |
statistics-secondsadded |
Statistics update |
статистика-толщинасегмента |
statistics-segmentthickness |
Statistics update |
статистика-толщинаканала |
statistics-channelthickness |
Statistics update |
статистика-ожиданиеответа |
statistics-responsewait |
Statistics update |
статистика-непросмотрено |
statistics-unwatched |
Statistics update |
All 9 IDs will cause crashes when the statistics overlay tries to update.
Since this is a pure naming mismatch, the fix is straightforward:
- Search
player.jsfor every occurrence of each Russian ID - Replace with the corresponding English ID from the table above
- Test the statistics overlay by pressing the 'S' key during playback
| Search For | Replace With |
|---|---|
Узел("статистика-сжатиевидео") |
Узел("statistics-videocompression") |
Узел("статистика-сервер") |
Узел("statistics-server") |
Узел("статистика-интервалобновления") |
Узел("statistics-updateinterval") |
Узел("статистика-сегментовдобавлено") |
Узел("statistics-segmentsadded") |
Узел("статистика-секунддобавлено") |
Узел("statistics-secondsadded") |
Узел("статистика-толщинасегмента") |
Узел("statistics-segmentthickness") |
Узел("статистика-толщинаканала") |
Узел("statistics-channelthickness") |
Узел("статистика-ожиданиеответа") |
Узел("statistics-responsewait") |
Узел("статистика-непросмотрено") |
Узел("statistics-unwatched") |
Important: Also search for these IDs without the Узел() wrapper — there may be direct document.getElementById() calls or string references.
After applying the fix:
-
Grep
player.jsfor all remaining Russian statistics IDs:grep -n "статистика-" player.js -
Load the extension in Chrome
-
Open a Twitch stream
-
Press S to open statistics overlay
-
Confirm all fields populate without crashes:
- Video Resolution
- Frame Rate
- Video Compression (primary bug location)
- Audio Compression
- Server
- All other statistics rows
-
Toggle statistics overlay multiple times during playback
-
Check browser console for any remaining
TypeErrorexceptions
Commit ebf05b5 performed partial translation: it updated the HTML IDs but forgot to update the JavaScript references. This is a classic incomplete refactoring bug.
- No automated tests — The extension has no test suite
- No type checking — Plain JavaScript with string-based DOM queries
- No CI/CD — Changes went directly to production
- Large file size —
player.jsis ~8,000 lines, making manual verification difficult
- Atomic commits — When changing IDs, update HTML and JS in the same commit
- Grep verification — Before committing ID changes, grep for all references:
grep -r "статистика-сжатиевидео" *.js *.html
- Manual testing checklist — Every commit that touches the statistics overlay should test the 'S' key
- Translation tracking — Use
Documentation/legacy_code_translation_reference.mdto track which identifiers have been renamed
The Узел() function (English alias: Node()) is a wrapper around document.getElementById() that:
- Accepts either a string ID or a DOM element
- Asserts that the result is a valid element node (
nodeType === 1) - Returns the element
This assertion is what exposes the bug immediately instead of allowing a null reference to propagate silently. While this makes debugging harder initially, it's actually a good defensive practice — it fails fast and clearly.
player-english-translating-test.js— Contains the same Russian IDs (test/reference file)Documentation/Translation/player.js.copy-english-translating.js— Static reference copy- CSS files may have related class names, but those don't cause runtime crashes
IMMEDIATE FIX REQUIRED:
Apply all 9 search/replace operations listed in the Fix Plan section to player.js, commit with message:
fix(player): update statistics overlay IDs to match HTML changes
Commit ebf05b5 changed HTML element IDs from Russian to English in
player.html but did not update the corresponding references in player.js.
This caused `document.getElementById()` to return null, resulting in a
TypeError when the statistics overlay tried to update.
All 9 Russian statistics IDs have been replaced with their English
equivalents:
- статистика-сжатиевидео → statistics-videocompression
- статистика-сервер → statistics-server
- (7 more listed in commit body)
Fixes: ebf05b5 ("Replace all Russian tooltip text with English")
Report prepared by: Claude Sonnet 4.5 Investigation method: Git forensics + static code analysis Confidence level: 100% — Root cause definitively identified