Guides
Limits and errors
Restrict what users can do per plan, react to refusals, and handle KymoscopeError codes.
Setting limits
const engine = createEngine({
limits: {
maxChartsPerWorksheet: 4,
maxChannelsPerChart: 4,
maxWorksheets: 4,
maxMathChannels: 4,
canImportExportWorkspaces: false,
},
})
// When the user's plan loads or changes:
engine.setOptions({ limits: planLimits })null means unlimited. setOptions({ limits }) merges into the current limits: keys you leave out keep their value.
When a limit is hit
The engine refuses the action, emits limit and throws KymoscopeError('limit_reached') with detail.reason.
| Reason | Triggered by |
|---|---|
charts-per-worksheet | charts.add or io.importChart on a full worksheet. |
channels-per-chart | charts.addSeries on a full multi-band chart. |
worksheets | worksheets.add or io.importWorksheet at the limit. |
workspaces-io | Any io export or import when canImportExportWorkspaces is false. |
math-channels | mathChannels.create, importMany or importFile with no room left. |
engine.on('limit', ({ reason }) => openUpgradeDialog(reason))
try {
engine.charts.add('histogram')
} catch (e) {
if (e instanceof KymoscopeError && e.code === 'limit_reached') return // the dialog is already open
throw e
}After a downgrade
Lowering limits never deletes anything. state.mathChannels only lists the channels within the limit, and the active worksheet is moved into the allowed range. Worksheets and charts beyond the limit stay in state.worksheets: slice them in your UI (the first maxWorksheets worksheets and the first maxChartsPerWorksheet charts), and they come back when the limit rises.
Error codes
Every failure is a KymoscopeError with a code and, where useful, a detail object. The full list is in Errors.
import { KymoscopeError } from '@kymoscope/sdk' // Kymoscope.KymoscopeError with the script tag
function run(fn: () => unknown) {
Promise.resolve().then(fn).catch((e) => {
if (e instanceof KymoscopeError && (e.code === 'limit_reached' || e.code === 'import_vetoed')) return
showError(e instanceof KymoscopeError ? e.code : String(e))
})
}