agalwood/Motrix · error · RangeError
kind is not a legal history event kind
Error message
kind is not a legal history event kind
What it means
`validateHistoryEventInput` requires `input.kind` to be one of the `TaskHistoryEventKind` enum values: `added`, `started`, `paused`, `resumed`, `stage_changed`, `completed`, `failed`, `observed_state`. The set is built once from `Object.values(...)`. A non-matching kind throws this `RangeError` before any state-machine checks run.
Source
Thrown at src/core/inspector-activity/validators.ts:171
throw new RangeError(
`${label} JSON must not exceed ${maxJsonLength} characters`
)
}
}
export function validateHistoryEventInput(input: TaskHistoryEventInput): void {
assertTaskId(input.taskId)
assertPositiveSafeInteger(input.eventOrdinal, 'eventOrdinal')
assertBoundedText(input.eventKey, 'eventKey', MAX_EVENT_KEY_LENGTH)
assertBoundedText(
input.runtimeGeneration,
'runtimeGeneration',
MAX_EVENT_KEY_LENGTH
)
assertPositiveSafeInteger(input.occurredAt, 'occurredAt')
assertNonNegativeSafeInteger(input.occurredMonotonicMs, 'occurredMonotonicMs')
if (!EVENT_KIND_VALUES.has(input.kind)) {
throw new RangeError('kind is not a legal history event kind')
}
if (!ACCURACY_VALUES.has(input.accuracy)) {
throw new RangeError('accuracy is not legal')
}
if (!DELIVERY_VALUES.has(input.delivery)) {
throw new RangeError('delivery is not legal')
}
assertStatus(input.fromStatus, 'fromStatus')
assertStatus(input.toStatus, 'toStatus')
if (input.toStatus === null) {
throw new RangeError('toStatus is required')
}
assertBoundedText(input.errorCode, 'errorCode', MAX_ERROR_CODE_LENGTH)
assertBoundedText(
input.errorMessage,
'errorMessage',
MAX_ERROR_MESSAGE_LENGTH
)View on GitHub (pinned to 1a708ee577)
Solutions
- Map the upstream event type through a lookup table that drops unmappable events.
- Reference `TaskHistoryEventKind.X` instead of literals so renames are tracked by the compiler.
- Quarantine events whose kind cannot be mapped and surface them in telemetry — do not submit them.
- Add a migration that backfills any renamed enum values in durable storage.
Example fix
// before
input.kind = engineEventType // 'begin' — not in enum
// after
const KIND_MAP: Record<string, TaskHistoryEventKind> = {
begin: TaskHistoryEventKind.Started,
}
input.kind = KIND_MAP[engineEventType]
if (input.kind === undefined) return Defensive patterns
Strategy: type-guard
Validate before calling
import { TaskHistoryEventKind } from '@shared/types/task-inspector-activity'
const KIND_VALUES = new Set(Object.values(TaskHistoryEventKind))
function coerceKind(v: unknown): TaskHistoryEventKind | null {
return typeof v === 'string' && KIND_VALUES.has(v) ? (v as TaskHistoryEventKind) : null
} Type guard
import { TaskHistoryEventKind } from '@shared/types/task-inspector-activity'
const KIND_VALUES = new Set(Object.values(TaskHistoryEventKind))
function isHistoryKind(v: unknown): v is TaskHistoryEventKind {
return typeof v === 'string' && KIND_VALUES.has(v)
} Prevention
- Import `TaskHistoryEventKind` enum members; never inline the string values.
- Translate external event types at the boundary.
- Drop, don't submit, unmappable events.
When it happens
Trigger: Submitting an event with a kind string from a foreign vocabulary, an old identifier (`'stop'` instead of `'paused'`), or accidentally passing the raw engine event type. Also fires when kind is `undefined`/empty after a bad deserialization.
Common situations: Bridging an external download engine's event names; replaying events from an older DB schema; tests using literals like `'started'` that later got renamed.
Related errors
- ${label} is not a legal task status
- accuracy is not legal
- delivery is not legal
- toStatus is required
- Added must not have a fromStatus
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/7091c79817b217a6.
Report an issue: GitHub.