Automattic/harper · error · Error
Unhandled case: ${arg}
Error message
Unhandled case: ${arg} What it means
serializeArg's final fallback: when an argument is not an Array, not string/number/boolean/undefined/bigint, has no to_json() method, and is not a plain object, the serializer has no way to represent it on the worker wire and throws 'Unhandled case: <arg>'. This rejects unsupported argument kinds (functions, symbols, Maps, Sets, class instances without to_json, etc.) at RPC time.
Source
Thrown at packages/harper.js/src/Serializer.ts:103
if (type === undefined) {
throw new Error('Unhandled case: type undefined');
}
return { json, type };
}
if (argType == 'object') {
return {
json: JSON.stringify(
await Promise.all(
Object.entries(arg).map(([key, value]) => this.serializeArg([key, value])),
),
),
type: 'object',
};
}
throw new Error(`Unhandled case: ${arg}`);
}
async serialize(req: DeserializedRequest): Promise<SerializedRequest> {
return {
procName: req.procName,
args: await Promise.all(req.args.map((arg) => this.serializeArg(arg))),
};
}
async deserializeArg(requestArg: RequestArg): Promise<any> {
const { Lint, Span, Suggestion } = await this.binary.getBinaryModule();
switch (requestArg.type) {
case 'bigint':
return BigInt(requestArg.json);
case 'undefined':
return undefined;
case 'boolean':View on GitHub (pinned to 5fe7d5ab76)
Solutions
- Convert the argument to a supported type before the call: plain object, array, string, number, boolean, bigint, or undefined
- Replace Map/Set with plain objects/arrays; convert Date to a number/string
- Remove callbacks or non-serializable values from the arguments
- If a needed type is missing, serialize it yourself (e.g. Array.from(map.entries())) or file an issue to extend Serializer
Example fix
// before
await linter.lint(text, [new Map([['a', 1]])]);
// after
await linter.lint(text, [{ a: 1 }]); Defensive patterns
Strategy: validation
Validate before calling
function isRpcSerializable(v: unknown): boolean {
return v === undefined || ['string','number','boolean','bigint'].includes(typeof v)
|| Array.isArray(v)
|| (typeof v === 'object' && v !== null && (typeof (v as any).to_json === 'function'
|| v.constructor?.name === 'Object'));
}
args.every(isRpcSerializable) || console.error('unsupported WorkerLinter arg', args); Try / catch
try {
return await linter.lint(text);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Unhandled case:')) {
console.error('Unsupported argument passed to WorkerLinter; normalize inputs.');
}
throw e;
} Prevention
- Convert Map/Set/Date to plain objects/arrays/primitives before calling linter methods
- Never pass functions, Symbols, or DOM objects into WorkerLinter calls
- Keep a typed wrapper around WorkerLinter so unsupported types are rejected at compile time
When it happens
Trigger: Calling a WorkerLinter method (lint, isLikelyEnglish, applySuggestion, ...) with arguments like a function, Symbol, Map/Set, DOM node, or a class instance lacking to_json() — anything outside the SerializableTypes surface.
Common situations: Passing a Map<string, ...> where a plain object was expected; accidentally passing a callback or Promise into lint config arguments; passing typed arrays or Dates.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Unhandled case: type undefined
- Unhandled case: ${requestArg.type}
- WorkerLinter has been disposed.
- Expected binary to be a string of url but got ${typeof binar
- Expected glue flavor to be "full" or "slim" but got ${glueFl
AI-assisted analysis of Automattic/harper@5fe7d5ab76 (2026-09-06).
Data as JSON: /api/errors/a7c8e256fcf3a766.
Report an issue: GitHub.