Hidden Assumptions in bokeh

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

Every codebase relies on things it never checks. Most of them are routine. CodeSea looked at bokeh/bokeh 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 a data source contains a column with incompatible data (like objects that Array.from() creates weird arrays from), get_array returns T[] but with wrong element types, causing type-unsafe operations downstream in GlyphView rendering

Worth your attention first

If hit testing occurs before rendering completes, accessing this.index throws 'index_data() wasn't called', breaking selection and interaction features silently until user clicks

Worth your attention first

If multiple bokeh plots try to use different WebGL contexts, they share the same ReglWrapper instance tied to the first context, causing rendering artifacts or crashes when switching between plots

Show everything (7 more)
Environment

WebGL extensions ['ANGLE_instanced_arrays', 'EXT_blend_minmax', 'OES_element_index_uint'] will be available in the browser context, but only checks if WebGL context creation succeeds

If this fails: If any required extension is missing, regl initialization may fail or glyphs render incorrectly without clear error messages, causing fallback to Canvas2D without user awareness

bokehjs/src/lib/models/glyphs/webgl/regl_wrap.ts:constructor
Scale

Factor arrays will contain reasonable numbers of unique string values (hundreds, not millions), but no bounds checking exists on the factors parameter length

If this fails: With millions of categorical factors, the mapping creation becomes O(n²) in memory and extremely slow, potentially causing browser tabs to hang or crash during coordinate transformation

bokehjs/src/lib/models/ranges/factor_range.ts:map_one_level
Temporal

Source files on disk won't change between dependency resolution and compilation phases, but no file locking or timestamp validation occurs

If this fails: If files are modified during the build process (common in watch mode), the compiler may use stale dependency graphs with fresh file contents, producing inconsistent builds or missing imports

bokehjs/src/compiler/build.ts:compiler host and file system operations
Contract

The SelectionManager will coordinate with GlyphRenderer views that have been properly initialized and connected through signals, but no validation ensures the renderer-datasource binding

If this fails: If a GlyphRenderer is created but not properly connected to its data source's selection signals, selection highlighting breaks—users can select points but visual feedback disappears, making multi-plot dashboards unusable

bokehjs/src/lib/models/sources/columnar_data_source.ts:selection_manager
Ordering

connect_signals() will be called after constructor but before any property changes or event callbacks are triggered, following a strict initialization order

If this fails: If properties are modified before connect_signals() runs, the _update_property_callbacks() won't be set up, causing js_property_callbacks to silently fail and custom JavaScript event handlers to never execute

bokehjs/src/lib/model.ts:connect_signals lifecycle
Domain

Factor tuples will consistently have the same nesting level throughout a single dataset (all L1Factor, all L2Factor, or all L3Factor), but no runtime validation enforces homogeneity

If this fails: Mixing factor levels like [['A'], ['B', 'C']] causes coordinate mapping to fail unpredictably—some categorical points render in wrong positions or disappear entirely from plots

bokehjs/src/lib/models/ranges/factor_range.ts:FactorSeq type system
Contract

Input JSON from stdin or argv.file will conform to the expected schema with 'code', 'lang', 'file', and 'bokehjs_dir' fields, but only validates file existence not content structure

If this fails: Malformed compilation requests cause JSON.parse() to throw or compile_and_resolve_deps() to fail with cryptic errors, breaking bokeh server's dynamic extension loading without clear error messages

bokehjs/src/compiler/main.ts:compile function

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

Full analysis of bokeh/bokeh →

Frequently Asked Questions

What does bokeh assume that could break in production?

The one most likely to cause trouble: Column data retrieved by string key will either be null, an array, or something that Array.from() can convert (assumes it's array-like), but never validates the key exists in schema or that the converted data has the expected element type If this fails, If a data source contains a column with incompatible data (like objects that Array.from() creates weird arrays from), get_array returns T[] but with wrong element types, causing type-unsafe operations downstream in GlyphView rendering

How many hidden assumptions does bokeh have?

CodeSea found 10 assumptions bokeh relies on but never validates, 3 of them critical, spanning Domain, Shape, Environment, Resource, Scale, Temporal, Contract, Ordering. 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.