{"record":{"id":"67ba41e76c501f2f","repo":"Hmbown/CodeWhale","slug":"maxbins-must-be-an-integer-in-16-1048576-pet-native","errorCode":null,"errorMessage":"maxBins must be an integer in [16, 1048576].","messagePattern":"maxBins must be an integer in \\[16, 1048576\\]\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pet/ios/Resources/pet-native.js","lineNumber":1313,"sourceCode":"exports.chooseLevel = chooseLevel;\nexports.binValue = binValue;\nexports.intensity = intensity;\nexports.totals = totals;\nexports.onsetSeries = onsetSeries;\nexports.autocorrelation = autocorrelation;\nexports.periodogram = periodogram;\nexports.unionDuration = unionDuration;\nconst model_js_1 = require(\"./model.js\");\nfunction emptyLevel(length, binMs) {\n    const n = model_js_1.CATEGORIES.length * length;\n    return { binMs, length, onsets: new Float64Array(n), activeMs: new Float64Array(n),\n        outputTokens: new Float64Array(n), cost: new Float64Array(n), errors: new Float64Array(n), peak: new Float64Array(n) };\n}\nconst FIELDS = ['onsets', 'activeMs', 'outputTokens', 'cost', 'errors'];\n/** O(events + channels × bins), including long intervals. No span-length inner loop. */\nfunction buildPyramid(events, requestedDuration, maxBins = 16_384) {\n    if (!Number.isInteger(maxBins) || maxBins < 16 || maxBins > 1_048_576)\n        throw new Error('maxBins must be an integer in [16, 1048576].');\n    let duration = requestedDuration ?? 1;\n    for (const e of events)\n        duration = Math.max(duration, e.endTime, e.startTime, e.status === 'error' ? (0, model_js_1.errorOnsetOf)(e) : 0);\n    if (!Number.isFinite(duration) || duration < 0)\n        throw new Error('Signal duration must be finite and nonnegative.');\n    duration = Math.max(1, duration);\n    const binMs = 2 ** Math.ceil(Math.log2(Math.max(1, duration / (maxBins - 1))));\n    const length = Math.floor(duration / binMs) + 1, fine = emptyLevel(length, binMs);\n    const stride = length + 1;\n    const activeDiff = new Float64Array(model_js_1.CATEGORIES.length * stride), tokenDiff = new Float64Array(model_js_1.CATEGORIES.length * stride);\n    for (const e of events) {\n        if (!Number.isFinite(e.startTime) || !Number.isFinite(e.endTime) || e.startTime < 0 || e.endTime < e.startTime)\n            throw new Error(`Invalid interval for ${e.id}.`);\n        const channel = model_js_1.CATEGORIES.indexOf(e.category);\n        if (channel < 0)\n            throw new Error(`Unknown category for ${e.id}.`);\n        const a = Math.floor(e.startTime / binMs), b = Math.floor(e.endTime / binMs);\n        const at = channel * length, diff = channel * stride;","sourceCodeStart":1295,"sourceCodeEnd":1331,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/pet/ios/Resources/pet-native.js#L1295-L1331","documentation":"buildPyramid validates its maxBins parameter: it must be an integer between 16 and 1,048,576 inclusive. This bound keeps the multi-resolution signal pyramid memory-bounded while ensuring enough resolution levels. Non-integers, values below 16, or values above 1M throw immediately.","triggerScenarios":"Calling buildPyramid(events, duration, maxBins) with maxBins = 0, a float like 100.5, a very large value above 1_048_576, or the argument omitted positionally so an options object landed in the maxBins slot.","commonSituations":"Config-driven bin counts read from user settings without clamping, NaN from a failed parseInt, or swapped arguments when calling with positional parameters.","solutions":["Pass an integer maxBins within [16, 1048576], e.g. 16384 (the default).","Clamp user/config values: Math.min(1_048_576, Math.max(16, Math.round(value))).","Omit the argument entirely to use the default 16384 instead of passing null/undefined explicitly where a number is required."],"exampleFix":"// before\nbuildPyramid(events, duration, settings.bins); // could be \"16384\"\n// after\nbuildPyramid(events, duration, Math.max(16, Math.min(1_048_576, parseInt(settings.bins, 10))));","handlingStrategy":"validation","validationCode":"const bins = Math.max(16, Math.min(1_048_576, Math.round(opts.maxBins ?? 16_384)));\nif (!Number.isInteger(bins)) throw new TypeError('maxBins must resolve to an integer');","typeGuard":"const isValidMaxBins = (v) => Number.isInteger(v) && v >= 16 && v <= 1_048_576;","tryCatchPattern":"try { buildPyramid(events, d, maxBins) } catch (err) { if (err.message.startsWith('maxBins')) return buildPyramid(events, d); throw err; }","preventionTips":["Clamp config-driven bin values before calling","Use the 16384 default unless you have a reason","Never pass options objects positionally into maxBins"],"tags":["parameters","validation","limits"],"backgroundTag":"argument-out-of-range","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}