{"record":{"id":"4422b0fb0e233992","repo":"moeru-ai/airi","slug":"the-ar-hmm-iteration-count-must-be-a-positive-inte","errorCode":null,"errorMessage":"The AR-HMM iteration count must be a positive integer.","messagePattern":"The AR-HMM iteration count must be a positive integer\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/motion-driver-magic/src/ar-hmm.ts","lineNumber":360,"sourceCode":"  for (let row = 0; row < rowCount - 1; row++) {\n    const values = alpha[row].flatMap((value, state) => parameters.states.map(\n      (_nextStateModel, nextState) => value + logTransitions[state][nextState] + emissions[row + 1][nextState] + beta[row + 1][nextState],\n    ))\n    const normalization = logSumExp(values)\n    for (let state = 0; state < options.stateCount; state++) {\n      for (let nextState = 0; nextState < options.stateCount; nextState++)\n        transitionCounts[state][nextState] += Math.exp(values[state * options.stateCount + nextState] - normalization)\n    }\n  }\n  return { gamma, transitionCounts, logLikelihood }\n}\n\n/** Creates a linear Gaussian AR-HMM model with deterministic clustering and EM updates. */\nexport function createArHmmModel(sequence: TrainingSequence, options: FitOptions): ArHmmModel {\n  if (options.stateCount < 2 || !Number.isInteger(options.stateCount))\n    throw new Error('The AR-HMM state count must be an integer greater than one.')\n  if (options.iterations < 1 || !Number.isInteger(options.iterations))\n    throw new Error('The AR-HMM iteration count must be a positive integer.')\n\n  const sourceModel = fitVarParameters(sequence, {\n    order: options.order,\n    ridge: options.ridge,\n  })\n  const rowCount = sourceModel.trainingFrames.length - options.order\n  if (rowCount < options.stateCount * (sourceModel.featureCount + 1))\n    throw new Error('The current motion is too short for this AR-HMM shape.')\n\n  const clusterFeatures = createClusterFeatures(sourceModel.trainingFrames, options.order)\n  const assignments = initializeAssignments(clusterFeatures, options.stateCount)\n  let expectation = createInitialExpectations(assignments, options.stateCount)\n  let stateParameters = maximizeParameters(sourceModel, expectation, options)\n  const logLikelihoods: number[] = []\n  for (let iteration = 0; iteration < options.iterations; iteration++) {\n    expectation = expectationStep(sourceModel, stateParameters, options)\n    logLikelihoods.push(expectation.logLikelihood)\n    stateParameters = maximizeParameters(sourceModel, expectation, options)","sourceCodeStart":342,"sourceCodeEnd":378,"githubUrl":"https://github.com/moeru-ai/airi/blob/9c213115f8bd0fff9e6eabab02b077ac32da21be/packages/motion-driver-magic/src/ar-hmm.ts#L342-L378","documentation":"EM fitting of the AR-HMM iterates `options.iterations` times; a count below 1 or non-integer makes the loop meaningless or impossible. The library validates this at the entry point before any fitting work.","triggerScenarios":"Calling `createArHmmModel(seq, { iterations: 0 })`, negative values, or a non-integer (e.g. 1.5). Also when iterations is computed dynamically (e.g. scaled by a quality factor) without rounding.","commonSituations":"A 'fast mode' config setting iterations to 0 intending 'auto'; dividing a time budget by per-iteration cost producing a fractional count; JSON config parsed as float (e.g. 3.0 stored as 3 but 2.5 typed by hand).","solutions":["Pass an integer `iterations >= 1`.","Coerce computed values: `Math.max(1, Math.round(budget / costPerIteration))`.","Validate the options object with a schema (integer, minimum 1) before calling.","Use the documented default iterations instead of a hand-computed value when unsure."],"exampleFix":"// before\ncreateArHmmModel(seq, { stateCount: 3, iterations: 0 })\n// after\ncreateArHmmModel(seq, { stateCount: 3, iterations: Math.max(1, Math.round(rawIterations)) })","handlingStrategy":"validation","validationCode":"function isValidIterations(n: unknown): n is number {\n  return typeof n === 'number' && Number.isInteger(n) && n >= 1\n}","typeGuard":null,"tryCatchPattern":"try {\n  const model = createArHmmModel(seq, options)\n} catch (error) {\n  if (error instanceof Error && error.message.includes('iteration count')) {\n    return createArHmmModel(seq, { ...options, iterations: 10 })\n  }\n  throw error\n}","preventionTips":["Round any computed iteration budget before passing it in.","Validate options with a schema before calling.","Replace magic 0 defaults with the library's documented default.","Type the config as integer (e.g. branded type) so bad values fail at parse time."],"tags":["validation","options","ar-hmm","motion"],"backgroundTag":"invalid-model-options","analyzedSha":"9c213115f8bd0fff9e6eabab02b077ac32da21be","analyzedAt":"2026-09-02T04:27:24.639Z","contentChangedAt":"2026-09-02T04:27:24.639Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}