NousResearch/hermes-agent · error · Error
Expected exported session JSON or JSONL
Error message
Expected exported session JSON or JSONL
What it means
normalizeImportSessions accepts (a) an array of session objects, (b) a single session object, or (c) a {sessions: [...]} export wrapper, and filters to plain objects. If any candidate item is null, a primitive, or an array, the counts diverge and this error is thrown — the file is neither a Hermes session export nor JSONL of session objects.
Source
Thrown at web/src/lib/session-import.ts:21
export type ImportableSession = Record<string, unknown>;
function normalizeImportSessions(value: unknown): ImportableSession[] {
const candidate =
value &&
typeof value === "object" &&
!Array.isArray(value) &&
Array.isArray((value as { sessions?: unknown }).sessions)
? (value as { sessions: unknown[] }).sessions
: Array.isArray(value)
? value
: [value];
const sessions = candidate.filter(
(item): item is ImportableSession =>
!!item && typeof item === "object" && !Array.isArray(item),
);
if (sessions.length !== candidate.length) {
throw new Error("Expected exported session JSON or JSONL");
}
return sessions;
}
export function parseImportSessions(text: string): ImportableSession[] {
const trimmed = text.trim();
if (!trimmed) throw new Error("File is empty");
try {
return normalizeImportSessions(JSON.parse(trimmed));
} catch (jsonError) {
const lines = trimmed.split(/\r?\n/).filter((line) => line.trim());
if (lines.length <= 1) throw jsonError;
return normalizeImportSessions(lines.map((line) => JSON.parse(line)));
}
}
export function importSummary(result: SessionImportResponse): string {View on GitHub (pinned to c896c09c42)
Solutions
- Re-export sessions from the source dashboard/hermes instance and import that file unmodified.
- Inspect the file: every element (or JSONL line) must be a JSON object representing one session.
- If migrating from another tool, write a converter that emits an array of session objects (or {sessions: [...]}) first.
Example fix
// before
[{ "id": "s1" }, "not-a-session"]
// after
[{ "id": "s1" }, { "id": "s2" }] Defensive patterns
Strategy: type-guard
Validate before calling
const looksLikeSessionExport = (v: unknown): boolean => {
const items = Array.isArray(v)
? v
: typeof v === 'object' && v !== null && Array.isArray((v as { sessions?: unknown }).sessions)
? (v as { sessions: unknown[] }).sessions
: [v]
return items.length > 0 && items.every(i => !!i && typeof i === 'object' && !Array.isArray(i))
}
if (!looksLikeSessionExport(parsed)) { rejectFile('Not a Hermes session export'); return } Type guard
function isPlainObject(v: unknown): v is Record<string, unknown> {
return typeof v === 'object' && v !== null && !Array.isArray(v)
} Try / catch
try {
const sessions = parseImportSessions(text)
} catch (err) {
if (String(err) === 'Expected exported session JSON or JSONL') {
showError('File must contain session objects (JSON array, {sessions:[...]}, or JSONL)')
return
}
throw err
} Prevention
- Only import files produced by the dashboard's own export.
- Validate the shape before mutating any import state.
- When converting from other tools, emit {sessions:[...]} with plain-object entries.
When it happens
Trigger: Importing a JSON file whose top-level array mixes session objects with strings/numbers; a wrapped export where sessions contains nulls; JSONL lines that parse to scalars; pasting an arbitrary API response into the import box.
Common situations: Hand-editing an export and corrupting entries; importing the wrong file (config dump, log file); exports from a different tool with a similar but incompatible shape.
Related errors
- File is empty
- That project has no folder to move into
- metadata must be JSON-serializable.
- tool args must be a mapping, got {type(args).__name__}
- Preview mode — launching is disabled.
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/dc3263ce6bc02436.
Report an issue: GitHub.