moeru-ai/airi · error · Error

The motion project source timeline is invalid.

Error message

The motion project source timeline is invalid.

What it means

After schema validation, parseLive2DMotionProject checks timeline invariants that the schema alone cannot express: the first source sample must start at atMs 0 and the last sample must not exceed project.durationMs. A violation means the source timeline does not cover/align with the project timeline and cannot be reliably resampled.

Source

Thrown at packages/stage-ui/src/features/devtools/motion/live2d/composables/keyframes.ts:459

export function parseLive2DMotionProject(raw: string): Live2DMotionProject {
  let input: unknown
  try {
    input = JSON.parse(raw)
  }
  catch {
    throw new Error('The file does not contain valid JSON.')
  }

  const result = safeParse(motionProjectSchema, input)
  if (!result.success)
    throw new Error('The file is not an AIRI Live2D motion project.')

  const project = result.output
  if (project.source.durationMs !== project.durationMs)
    throw new Error('The motion project source is invalid.')

  if (project.source.samples[0].atMs !== 0 || project.source.samples.at(-1)!.atMs > project.durationMs)
    throw new Error('The motion project source timeline is invalid.')
  for (let index = 1; index < project.source.samples.length; index++) {
    if (project.source.samples[index].atMs < project.source.samples[index - 1].atMs)
      throw new Error('The motion project source samples are not in time order.')
  }

  for (const overlay of project.overlays) {
    if (overlay.endMs > project.durationMs || overlay.startMs > overlay.endMs)
      throw new Error('The motion project contains an invalid overlay span.')
    if (overlay.points.some(point => point.atMs < overlay.startMs || point.atMs > overlay.endMs))
      throw new Error('The motion project contains an invalid overlay point.')
    for (let index = 1; index < overlay.points.length; index++) {
      if (overlay.points[index].atMs < overlay.points[index - 1].atMs)
        throw new Error('The motion project overlay points are not in time order.')
    }
  }
  return structuredClone(project)
}

View on GitHub (pinned to 9c213115f8)

Solutions

  1. Ensure the first sample has atMs: 0; rebase all sample timestamps by subtracting samples[0].atMs.
  2. Remove or clamp samples whose atMs exceeds project.durationMs, or increase durationMs to cover the last sample.
  3. Re-export the project from the AIRI motion devtools to regenerate a correctly aligned sample timeline.

Example fix

// before
samples: [{ atMs: 120, values: {...} }, { atMs: 2400, values: {...} }] // durationMs: 2000
// after
samples: [{ atMs: 0, values: {...} }, { atMs: 2000, values: {...} }]
Defensive patterns

Strategy: validation

Validate before calling

function hasAlignedTimeline(parsed) {
  const samples = parsed?.source?.samples
  if (!Array.isArray(samples) || samples.length === 0)
    return false
  return samples[0].atMs === 0
    && samples[samples.length - 1].atMs <= parsed.durationMs
}

Try / catch

try {
  const project = parseLive2DMotionProject(raw)
}
catch (error) {
  if (error.message === 'The motion project source timeline is invalid.') {
    notifyUser('Motion samples do not align with the project timeline (must start at 0ms and end within durationMs).')
  }
  else throw error
}

Prevention

When it happens

Trigger: Parsing a project whose source.samples[0].atMs is not 0 (e.g. samples start at 100ms) or whose last sample's atMs exceeds project.durationMs (e.g. last sample at 2500ms with durationMs 2000).

Common situations: Hand-trimming sample arrays without rebasing timestamps to 0; cropping samples externally and leaving the original end timestamp; exporter bug writing samples beyond the declared duration.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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