moeru-ai/airi · error · Error

The VAR order must be a positive integer.

Error message

The VAR order must be a positive integer.

What it means

The VAR model uses `options.order` past frames to predict the current frame; an order below 1 or non-integer yields no autoregressive window or malformed lag matrices, so it is rejected at the top of `fitVarParameters`.

Source

Thrown at packages/motion-driver-magic/src/shared/var.ts:75

}

function createResiduals(frames: readonly number[][], coefficients: readonly number[][], order: number): number[][] {
  const channelCount = frames[0].length
  const residuals: number[][] = []
  for (let frameIndex = order; frameIndex < frames.length; frameIndex++) {
    const feature = createAutoregressiveFeature(frames, order, channelCount, frameIndex)
    const prediction = predictAutoregressiveValues(coefficients, feature)
    residuals.push(frames[frameIndex].map((value, channel) => value - prediction[channel]))
  }
  return residuals
}

/** Fits the VAR parameters that both public methods use. */
export function fitVarParameters(sequence: TrainingSequence, options: VarFitOptions): VarParameters {
  if (!Number.isFinite(sequence.sampleRateHz) || sequence.sampleRateHz <= 0)
    throw new Error('The motion sample rate must be positive.')
  if (options.order < 1 || !Number.isInteger(options.order))
    throw new Error('The VAR order must be a positive integer.')

  const frames = sequence.frames
  if (frames.length === 0 || frames[0].length === 0)
    throw new Error('The motion sequence must contain at least one value.')
  if (frames.some(frame => frame.length !== frames[0].length))
    throw new Error('Every motion frame must have the same number of values.')

  const channels = createMotionChannels(frames)
  if (channels.length === 0)
    throw new Error('The current motion has no changing channels.')
  if (frames.length <= options.order + 1)
    throw new Error('The current motion is too short for this VAR order.')

  const baselineFrame = createBaselineFrame(frames)
  const trainingFrames = frames.map(frame => channels.map(
    channel => (frame[channel.valueIndices[0]] - channel.mean) / channel.scale,
  ))
  const coefficients = fitCoefficients(trainingFrames, options)

View on GitHub (pinned to 9c213115f8)

Solutions

  1. Pass an integer `order >= 1`.
  2. Round/clamp computed values: `Math.max(1, Math.round(rawOrder))`.
  3. Validate options with a schema (integer, minimum 1) before fitting.
  4. Keep order well below the frame count — remember rows are reduced by `order` during fitting.

Example fix

// before
fitVarParameters(seq, { order: 0, ridge: 1e-6 })
// after
fitVarParameters(seq, { order: Math.max(1, Math.round(rawOrder)), ridge: 1e-6 })
Defensive patterns

Strategy: validation

Validate before calling

function isValidOrder(n: unknown): n is number {
  return typeof n === 'number' && Number.isInteger(n) && n >= 1
}

Try / catch

try {
  fitVarParameters(seq, options)
} catch (error) {
  if (error instanceof Error && error.message.includes('VAR order')) {
    return fitVarParameters(seq, { ...options, order: 2 })
  }
  throw error
}

Prevention

When it happens

Trigger: Calling `fitVarParameters` or `createArHmmModel` with `order: 0`, negative order, or fractional values (e.g. computed as `dataSeconds * 2` = 2.5). Also when order comes from a slider storing floats.

Common situations: Config default of 0 meaning 'auto'; a UI slider emitting floats; dividing total lag seconds by frame time without rounding; copying an example and editing order to '0 to disable' not realizing it is invalid.

Related errors


AI-assisted analysis of moeru-ai/airi@9c213115f8 (2026-09-02). Data as JSON: /api/errors/b918d6671edb7460. Report an issue: GitHub.