tinyhumansai/openhuman · error

mascot manifest: missing mascots array

Error message

mascot manifest: missing mascots array

What it means

parseManifest() validates the fetched mascot library manifest document. It throws 'mascot manifest: missing mascots array' when the parsed JSON is null/undefined or lacks a mascots property that is an Array. This is a hard failure on a fundamentally malformed payload — the fetch succeeded (HTTP 200) but the body does not resemble a manifest at all.

Source

Thrown at app/src/features/human/Mascot/manifest/manifestService.ts:112

    (!Array.isArray(se.channels) || !se.channels.every(isManifestChannel))
  ) {
    return false;
  }
  if (!Array.isArray(m.files) || !m.files.every(isManifestFile)) return false;
  // A renderable mascot needs a runtime `.riv`; drop entries that only ship a
  // source `.rev` so callers never select an unplayable asset.
  return !!runtimeFile(m as MascotManifestEntry);
}

/**
 * Validate and normalise a parsed manifest document. Throws on a
 * fundamentally malformed payload; silently drops individual malformed
 * mascot entries (a single bad entry should never blank the whole library).
 */
export function parseManifest(raw: unknown): MascotManifest {
  const doc = raw as Partial<MascotManifest> | null;
  if (!doc || !Array.isArray(doc.mascots)) {
    throw new Error('mascot manifest: missing mascots array');
  }
  const mascots = doc.mascots.filter(isManifestEntry);
  if (mascots.length === 0) {
    throw new Error('mascot manifest: no renderable mascots');
  }
  return {
    schemaVersion: typeof doc.schemaVersion === 'number' ? doc.schemaVersion : 1,
    generatedAt: isNonEmptyString(doc.generatedAt) ? doc.generatedAt : '',
    mascots,
    source: {
      repository: doc.source?.repository ?? '',
      branch: doc.source?.branch ?? '',
      commit: doc.source?.commit ?? '',
    },
  };
}

function readSnapshot(): MascotManifest | null {

View on GitHub (pinned to 7491200858)

Solutions

  1. Open MASCOT_MANIFEST_URL in a browser/curl and inspect the body — confirm it is JSON with a top-level "mascots": [...] array.
  2. If the body is HTML (repo renamed, Pages fallback), update MASCOT_MANIFEST_URL to the correct manifest location.
  3. If the manifest is genuinely broken upstream, fix the generator to always emit the mascots array; note fetchMascotManifest() falls back to an IndexedDB/localStorage snapshot when available, so clearing the snapshot store makes the failure reproducible.
  4. As a consumer, catch the error and fall back to a bundled default manifest instead of blanking the mascot feature.

Example fix

// before
const manifest = parseManifest(await res.json());

// after — hard-fail only on truly wrong shape, else fall back
let manifest: MascotManifest;
try {
  manifest = parseManifest(await res.json());
} catch (err) {
  manifest = bundledFallbackManifest; // shipped default
  warnLog('mascot manifest unusable, using bundled fallback', err);
}
Defensive patterns

Strategy: validation

Validate before calling

const raw: unknown = await res.json();
const looksLikeManifest =
  !!raw && typeof raw === 'object' && Array.isArray((raw as any).mascots);
if (!looksLikeManifest) { /* use fallback manifest */ }

Type guard

function isManifestDoc(v: unknown): v is { mascots: unknown[] } {
  return !!v && typeof v === 'object' && Array.isArray((v as { mascots?: unknown }).mascots);
}

Try / catch

try {
  manifest = parseManifest(raw);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('mascot manifest:')) {
    manifest = bundledFallback;
  } else throw err;
}

Prevention

When it happens

Trigger: fetchMascotManifest() receives a 200 response whose JSON body is null, an empty object, or has mascots as a non-array (string, object, number). Typical causes: CDN/GitHub Pages returning an HTML error or SPA fallback page that happens to parse as JSON-null, a truncated JSON body, or a manifest generation script emitting {schemaVersion, generatedAt} without the mascots key.

Common situations: The manifest URL (MASCOT_MANIFEST_URL) points at a raw.githubusercontent/Pages URL that 404s into an HTML fallback; a CI job regenerated the manifest with a bug dropping the array; an upstream repo restructured and renamed the manifest file; response caching serving a corrupted body.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/8c1a9847a8f6cb8c. Report an issue: GitHub.