angular/angular-cli · error
Expected a JobHandler as second argument.
Error message
Expected a JobHandler as second argument.
What it means
SimpleJobRegistry.register() accepts either a job name string plus a handler, or a bare JobHandler object. When the first argument is a string, the second argument must be a valid JobHandler; this TypeError is thrown when isJobHandler(handlerOrOptions) fails, i.e. the second argument is not a function/object with the expected job-handler shape.
Source
Thrown at packages/angular_devkit/architect/src/jobs/simple-registry.ts:76
* @param handler The function that will be called for the job.
* @param options An optional list of options to override the handler. {@see RegisterJobOptions}
*/
register<ArgumentT extends JsonValue, InputT extends JsonValue, OutputT extends JsonValue>(
handler: JobHandler<ArgumentT, InputT, OutputT>,
// This version MUST contain a name.
options?: RegisterJobOptions & { name: string },
): void;
register<ArgumentT extends JsonValue, InputT extends JsonValue, OutputT extends JsonValue>(
nameOrHandler: JobName | JobHandler<ArgumentT, InputT, OutputT>,
handlerOrOptions: JobHandler<ArgumentT, InputT, OutputT> | RegisterJobOptions = {},
options: RegisterJobOptions = {},
): void {
// Switch on the arguments.
if (typeof nameOrHandler == 'string') {
if (!isJobHandler(handlerOrOptions)) {
// This is an error.
throw new TypeError('Expected a JobHandler as second argument.');
}
this._register(nameOrHandler, handlerOrOptions, options);
} else if (isJobHandler(nameOrHandler)) {
if (typeof handlerOrOptions !== 'object') {
// This is an error.
throw new TypeError('Expected an object options as second argument.');
}
const name = options.name || nameOrHandler.jobDescription.name || handlerOrOptions.name;
if (name === undefined) {
throw new TypeError('Expected name to be a string.');
}
this._register(name, nameOrHandler, options);
} else {
throw new TypeError('Unrecognized arguments.');
}View on GitHub (pinned to bb72145f9a)
Solutions
- Pass a valid JobHandler (created via createJobHandler) as the second argument: registry.register('my-job', createJobHandler(() => ..., { name: 'my-job' })).
- Check argument order: register(name, handler, options) — swap the second and third arguments if an options object was passed second.
- If registering a bare handler, drop the string and call register(handler) or register(handler, { name: 'my-job' }) so the name is inferred from jobDescription.name.
- Log or inspect the second argument's type just before the call to confirm it is the handler, not a Promise resolving to one (await it first).
Example fix
// before
registry.register('build-job', { name: 'build-job', description: 'build' });
// after
registry.register('build-job', createJobHandler(() => of({ success: true }), { name: 'build-job', description: 'build' })); Defensive patterns
Strategy: type-guard
Validate before calling
const { isJobHandler } = require('@angular-devkit/architect');
if (typeof nameOrHandler === 'string' && !isJobHandler(handlerOrOptions)) {
throw new Error('second argument must be a JobHandler');
} Type guard
function isHandler(v) {
return v != null && (typeof v === 'function' || (typeof v === 'object' && typeof v.handler === 'function' && v.jobDescription && typeof v.jobDescription.name === 'string'));
} Try / catch
try {
registry.register(name, handler);
} catch (e) {
if (e instanceof TypeError && /JobHandler as second argument/.test(e.message)) {
throw new Error(`register('${name}') got a non-handler second argument: ${typeof handler}`);
}
throw e;
} Prevention
- Always create handlers with createJobHandler rather than plain functions
- Keep argument order (name, handler, options) consistent; consider using the handler-only form with options.name
- Check isJobHandler(x) in unit tests before registering
- Beware of Promises: await handler factories before calling register
When it happens
Trigger: Calling registry.register('job-name', <something that is not a JobHandler>) — e.g. passing the wrong variable, a plain function missing jobDescription/argument/input/output properties, or passing the options object as the second argument by mistake.
Common situations: Passing arguments in the wrong order (name, options, handler) instead of (name, handler, options); passing a plain callback from an older job API after an Angular DevKit version change; refactoring that replaced a handler with a factory return value.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- Expected an object options as second argument.
- Expected name to be a string.
- Unrecognized arguments.
- Could not find the '${builderConf}' builder's node package.
- Cannot determine project for command. This is a multi-projec
AI-assisted analysis of angular/angular-cli@bb72145f9a (2026-08-30).
Data as JSON: /api/errors/de52884edc518424.
Report an issue: GitHub.