eyaltoledano/claude-task-master · error · Error

`Unknown executor type: ${options.type}`

Error message

`Unknown executor type: ${options.type}`

What it means

Plain Error thrown by ExecutorFactory.create when options.type does not match any known executor type (not 'claude', 'shell', or 'custom'). The actual value is interpolated into the message. This is the factory's exhaustive-switch guard against invalid input.

Source

Thrown at packages/tm-core/src/modules/execution/executors/executor-factory.ts:31

	 * Create an executor based on the provided options
	 */
	static create(options: ExecutorOptions): ITaskExecutor {
		this.logger.debug(`Creating executor of type: ${options.type}`);

		switch (options.type) {
			case 'claude':
				return new ClaudeExecutor(options.projectRoot, options.config);

			case 'shell':
				// Placeholder for shell executor
				throw new Error('Shell executor not yet implemented');

			case 'custom':
				// Placeholder for custom executor
				throw new Error('Custom executor not yet implemented');

			default:
				throw new Error(`Unknown executor type: ${options.type}`);
		}
	}

	/**
	 * Get the default executor type based on available tools
	 */
	static async getDefaultExecutor(
		projectRoot: string
	): Promise<ExecutorType | null> {
		// Check for Claude first
		const claudeExecutor = new ClaudeExecutor(projectRoot);
		if (await claudeExecutor.isAvailable()) {
			this.logger.info('Claude CLI detected as default executor');
			return 'claude';
		}

		// Could check for other executors here
		this.logger.warn('No default executor available');

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Set options.type to 'claude' (currently the only implemented type) or omit it to use the default
  2. Check the interpolated type value in the message and fix casing/typos ('claude', not 'Claude')
  3. Validate the value against the supported set before calling create
  4. Migrate old config files after upgrading if executor type names changed
  5. Narrow the type with a union ('claude' | 'shell' | 'custom') in your own typing to catch it at compile time

Example fix

// before
const exec = ExecutorFactory.create({ type: (config.executor as string), projectRoot });
// after
type ExecutorType = 'claude' | 'shell' | 'custom';
const t: ExecutorType = config.executor ?? 'claude';
if (!['claude','shell','custom'].includes(t)) throw new Error(`bad executor: ${t}`);
const exec = ExecutorFactory.create({ type: t, projectRoot });
Defensive patterns

Strategy: type-guard

Validate before calling

const VALID = ['claude', 'shell', 'custom'] as const;
if (!VALID.includes(options.type as any)) {
  throw new Error(`Invalid executor type: ${options.type}`);
}

Type guard

function isValidExecutorType(t: unknown): t is 'claude' | 'shell' | 'custom' {
  return t === 'claude' || t === 'shell' || t === 'custom';
}

Try / catch

try {
  executor = ExecutorFactory.create({ type, projectRoot });
} catch (e) {
  if (e.message.startsWith('Unknown executor type')) {
    executor = ExecutorFactory.create({ projectRoot }); // default
  } else throw e;
}

Prevention

When it happens

Trigger: Calling ExecutorFactory.create with type values like 'bash', 'claude-code', 'Claude' (wrong case), an empty string, or a typo from a parsed config/command-line value.

Common situations: Loose string from user config or CLI flag passed through unvalidated; case-sensitivity mistakes ('Claude'); renaming executor types after a version upgrade so old configs carry stale values.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29). Data as JSON: /api/errors/00552ee3a0bcba94. Report an issue: GitHub.