agalwood/Motrix · error · AppError
IpcInvalidPayload
IpcInvalidPayload
Error message
Invalid Task Inspector Activity query params
What it means
Thrown by the Task Inspector Activity query when the params passed to snapshot() are not a plain object. The guard rejects anything that is not an object, is null, or whose prototype is neither Object.prototype nor null — defending the IPC boundary against arrays, class instances, primitives, and cross-realm objects. Categorized as IpcInvalidPayload.
Source
Thrown at src/core/inspector-activity/task-inspector-activity-query.ts:30
* Test-only fault injection. The first valid query delegates normally and
* every later query fails without touching the runtime.
*/
failAfterFirstQuery?: boolean
}
export interface TaskInspectorActivityQuery {
snapshot(params: unknown): TaskInspectorActivitySnapshot
}
export function createTaskInspectorActivityQuery(
reader: TaskInspectorActivitySnapshotReader,
options: TaskInspectorActivityQueryOptions = {}
): TaskInspectorActivityQuery {
let queryCount = 0
return {
snapshot(params: unknown): TaskInspectorActivitySnapshot {
const invalid = (): never => {
throw new AppError(
ErrorCode.IpcInvalidPayload,
'Invalid Task Inspector Activity query params'
)
}
if (
typeof params !== 'object' ||
params === null ||
(Object.getPrototypeOf(params) !== Object.prototype &&
Object.getPrototypeOf(params) !== null)
) {
return invalid()
}
const keys = Reflect.ownKeys(params)
if (keys.length !== 1 || keys[0] !== 'taskId') {
return invalid()
}
const descriptor = Object.getOwnPropertyDescriptor(params, 'taskId')
if (!descriptor || !('value' in descriptor)) {View on GitHub (pinned to 1a708ee577)
Solutions
- Always pass a plain object: query.snapshot({ taskId: '...', ... }) — never a primitive, array, or class instance.
- On the IPC sender side, JSON.stringify then parse to strip prototypes before calling.
- Default params to {} at the call site so an omitted argument cannot reach the guard.
- If you must accept a class instance, serialize it to a POJO first.
Example fix
// before
const snap = query.snapshot(someClassInstance) // throws IpcInvalidPayload
// after
const snap = query.snapshot({ taskId: someClassInstance.taskId, range: { from: 0, to: 100 } }) Defensive patterns
Strategy: type-guard
Validate before calling
// Only pass plain-object params to snapshot.
function toPlainParams(p: unknown): Record<string, unknown> {
if (typeof p !== 'object' || p === null) return {}
return Object.getPrototypeOf(p) === Object.prototype || Object.getPrototypeOf(p) === null ? p as Record<string, unknown> : { ...p }
} Type guard
function isPlainObject(v: unknown): v is Record<string, unknown> {
if (typeof v !== 'object' || v === null) return false
const proto = Object.getPrototypeOf(v)
return proto === Object.prototype || proto === null
} Try / catch
if (!isPlainObject(params)) {
// reject the IPC call with a 400-style response; do not call snapshot
}
const snap = query.snapshot(params) Prevention
- Always pass object literals ({...}) over IPC.
- JSON round-trip payloads at the boundary to strip prototypes.
- Default optional params to {}.
- Never forward class instances or arrays as the params root.
When it happens
Trigger: snapshot(params) is called with params that is not a plain object literal: an array, a class instance, a primitive (string/number/boolean), null/undefined, or an object from another realm/VM context whose prototype chain differs.
Common situations: IPC renderer sending a raw primitive or array instead of a params object; a class instance leaking across the IPC boundary instead of a serialized POJO; an undefined default when no argument was supplied; a cross-realm/electron-remote object.
Related errors
- taskId must be a string
- Key must be 16 bytes, got ${key.length}
- IV must be 16 bytes, got ${iv.length}
- plugin.http.response_type_required
- plugin.metadata.value_not_serializable
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/772754cb95e1c6fe.
Report an issue: GitHub.