moeru-ai/airi · error · InvalidCharacterCardError

Invalid Character Card V3.

Error message

Invalid Character Card V3.

What it means

Thrown as InvalidCharacterCardError by parseCharacterCardV3() when valibot's safeParse against characterCardV3Schema fails. The schema enforces spec === 'chara_card_v3', a dotted spec_version, and a nested data object with required string fields; failure means the input is structurally not a CCv3 card. The error's cause carries the valibot issues and .source carries the original input.

Source

Thrown at packages/ccc/src/codec/characterCardV3.ts:179

/** Checks whether an error came from the CCv3 parsing boundary. */
export function isInvalidCharacterCardError(error: unknown): error is InvalidCharacterCardError {
  return error instanceof InvalidCharacterCardError
}

/**
 * Parses and validates a Character Card V3 object or JSON document.
 *
 * Unknown fields are preserved so a newer card can be inspected and exported
 * without silently discarding data AIRI does not understand yet. Older and
 * newer `spec_version` values are accepted and reported through
 * `compatibility`; callers can decide how prominently to warn users.
 */
export function parseCharacterCardV3(source: unknown): ParsedCharacterCardV3 {
  const candidate = parseJsonSource(source)
  const result = safeParse(characterCardV3Schema, candidate)

  if (!result.success) {
    throw new InvalidCharacterCardError({
      cause: result.issues,
      source,
    })
  }

  return {
    card: result.output,
    compatibility: resolveCompatibility(result.output.spec_version),
  }
}

function parseJsonSource(source: unknown): unknown {
  if (typeof source !== 'string')
    return source

  try {
    return JSON.parse(source)
  }

View on GitHub (pinned to 27111382b4)

Solutions

  1. Inspect error.cause (valibot issues) to see the exact failing path and expected type.
  2. Upgrade V2 cards to V3: set spec='chara_card_v3', spec_version='3.0', and nest fields under data.
  3. If you must accept older cards, detect the version first and run the V2/V1 parser instead of parseCharacterCardV3.
  4. Validate with a JSON schema tool upstream and surface field-level errors to the user.

Example fix

// before
const parsed = parseCharacterCardV3(cardJsonV2) // { spec: 'chara_card_v2', name: ... }
// after
const v3 = { spec: 'chara_card_v3', spec_version: '3.0', data: { ...cardJsonV2, alternate_greetings: [], group_only_greetings: [], tags: [], ... } }
const parsed = parseCharacterCardV3(v3)
Defensive patterns

Strategy: try-catch

Validate before calling

import { safeParse } from 'valibot'
// Validate shape upstream with the same schema exports if available, else a lightweight check:
function looksLikeV3(card: unknown): boolean {
  return !!card && typeof card === 'object' && (card as any).spec === 'chara_card_v3' && !!(card as any).data
}

Type guard

import { isInvalidCharacterCardError } from '@proj-airi/ccc'
// isInvalidCharacterCardError narrows the thrown error type after catch
function isCardLike(v: unknown): v is { spec: unknown; data: unknown } {
  return !!v && typeof v === 'object' && 'spec' in v && 'data' in v
}

Try / catch

import { isInvalidCharacterCardError, parseCharacterCardV3 } from '@proj-airi/ccc'

try {
  const parsed = parseCharacterCardV3(input)
} catch (error) {
  if (isInvalidCharacterCardError(error)) {
    console.error('Card rejected. Issues:', error.cause)
    // surface error.cause (valibot issues) to the user
  }
  throw error
}

Prevention

When it happens

Trigger: Passing an object or JSON string that is missing required fields (e.g. no data.name, data.first_mes), has spec set to 'chara_card_v2', uses wrong types (alternate_greetings not a string array), or a spec_version that does not match /^\d+(?:\.\d+)*$/.

Common situations: Loading a Character Card V2 file into a V3-only parser; user-uploaded card missing required fields; hand-edited JSON with a typo in spec or spec_version; a card exported by a tool that omits empty strings; downstream code that assumes any JSON object is a valid card.

Understand the failure class

Related errors


AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12). Data as JSON: /api/errors/4fe09063add39858. Report an issue: GitHub.