Hidden Assumptions in analytics

12 assumptions this code never checks · 4 critical · spanning Shape, Environment, Domain, Temporal, Ordering, Scale, Resource, Contract

Every codebase relies on things it never checks. Most of them are routine. CodeSea looked at plausible/analytics and picked out the few most likely to cause trouble. The full list is just below.

Most of what this code assumes is routine. These 3 are the ones most likely to cause trouble here. The rest are minor; they're under "Show everything".

Worth your attention first

If event target is null, undefined, or doesn't have contains method, modal throws TypeError and breaks click-outside-to-close functionality

Worth your attention first

Circular references in changeset data cause infinite recursion and stack overflow during audit logging, potentially crashing the process

Worth your attention first

In server-side rendering or non-browser environments, accessing document.body.style throws reference error and prevents modal rendering

Show everything (9 more)
Environment

Cross-origin fetch to https://plausible.io/changes.txt will always succeed and return valid text response - assumes network availability, CORS headers, and server uptime

If this fails: Network failures or CORS issues cause silent Promise rejection, leaving changelog notification in inconsistent state with no error handling

assets/js/app.js:changelogNotification
Domain

Browser names from user agent parsing exactly match BROWSER_ICONS keys - assumes consistent string formatting between user agent parser and icon mapping

If this fails: Unrecognized browser names fall back to 'fallback.svg' which may not exist, causing broken image icons in device reports

assets/js/dashboard/stats/devices/index.js:browserIconFor
Temporal

localStorage.lastChangelogUpdate contains valid timestamp number that can be parsed - assumes previous successful fetch stored valid Date.getTime() value

If this fails: Invalid or corrupted timestamp values cause NaN comparisons, potentially showing changelog notification incorrectly or never

assets/js/app.js:showChangelogNotification
Ordering

parseSearch(location.search) returns object with expected filter structure before postProcessFilters runs - assumes URL parsing happens before filter processing

If this fails: Malformed URL search params could pass undefined or invalid filter arrays to postProcessFilters, causing dashboard state corruption

assets/js/dashboard/dashboard-state-context.tsx:useMemo
Scale

Goal names in localStorage keys are URL-safe and don't contain special characters - assumes goal names from API responses are sanitized for storage key usage

If this fails: Goal names with special characters create invalid localStorage keys, causing prop key storage/retrieval to fail silently for those goals

assets/js/dashboard/stats/behaviours/index.js:STORAGE_KEYS.getForPropKeyForGoal
Resource

Window innerWidth is available and returns valid number - assumes browser window object exists with width measurement capability

If this fails: In headless or server environments where window.innerWidth is undefined, modal sizing falls back to DEFAULT_WIDTH but resize handler may throw errors

assets/js/dashboard/stats/modals/modal.js:DEFAULT_WIDTH
Contract

ListReport component expects getFilterInfo to return object with specific shape {prefix: string, filter: [string, string, string[]]} - assumes consistent filter structure contract

If this fails: If getFilterInfo returns different structure, ListReport filter application fails silently or throws errors when constructing dashboard queries

assets/js/dashboard/stats/pages/index.js:getFilterInfo
Environment

BUILD_EXTRA global is defined at compile time and controls conditional module loading - assumes build system sets this flag correctly

If this fails: If BUILD_EXTRA is undefined, maybeRequire() behavior is unpredictable and could break funnel functionality in production builds

assets/js/dashboard/stats/behaviours/index.js:BUILD_EXTRA
Temporal

Modal cleanup happens in exact reverse order of setup - assumes removeEventListener calls match addEventListener pairs from componentDidMount

If this fails: If component unmounts during event handling or if event listeners were modified elsewhere, cleanup may miss listeners causing memory leaks

assets/js/dashboard/stats/modals/modal.js:componentWillUnmount

See the full structural analysis of analytics: the pipeline, data models, and system behavior that put these assumptions in context.

Full analysis of plausible/analytics →

Frequently Asked Questions

What does analytics assume that could break in production?

The one most likely to cause trouble: Mouse events have target property that points to DOM elements that respond to contains() method - assumes e.target is a node and this.node.current is a DOM element with contains method If this fails, If event target is null, undefined, or doesn't have contains method, modal throws TypeError and breaks click-outside-to-close functionality

How many hidden assumptions does analytics have?

CodeSea found 12 assumptions analytics relies on but never validates, 4 of them critical, spanning Shape, Environment, Domain, Temporal, Ordering, Scale, Resource, Contract. Most are routine — the analysis flags the two or three most likely to actually bite.

What is a hidden assumption?

Something the code depends on but never checks: a data shape, an ordering, an environment condition, a scale limit, or a contract with another service. It holds until the world it runs in changes, then fails silently.