eyaltoledano/claude-task-master · error · Error

Shell executor not yet implemented

Error message

Shell executor not yet implemented

What it means

Plain Error thrown by ExecutorFactory.create when options.type is 'shell'. The shell executor is a declared but unimplemented placeholder in the factory switch, so requesting it always throws. It is a library capability gap, not a runtime fault.

Source

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

import { ClaudeExecutor } from '../executors/claude-executor.js';
import type { ExecutorOptions, ExecutorType, ITaskExecutor } from '../types.js';

export class ExecutorFactory {
	private static logger = getLogger('ExecutorFactory');

	/**
	 * 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);

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Use type: 'claude' which is the implemented executor
  2. Omit options.type and let the factory pick the default via getDefaultExecutorType()
  3. Check the installed @tm/core version / changelog for shell executor availability and upgrade when it ships
  4. If you need shell semantics, wrap your command in a script the Claude executor can run, or contribute a ShellExecutor implementing the Executor interface
  5. Validate user/config-supplied executor type against the supported set before calling create

Example fix

// before
const exec = ExecutorFactory.create({ type: 'shell', projectRoot });
// after
const exec = ExecutorFactory.create({ type: 'claude', projectRoot });
Defensive patterns

Strategy: validation

Validate before calling

type SupportedExecutor = 'claude';
function assertImplemented(t: string): asserts t is SupportedExecutor {
  if (t !== 'claude') throw new Error(`Executor '${t}' not implemented; use 'claude'`);
}

Type guard

const isImplementedExecutor = (t: unknown): t is 'claude' =>
  typeof t === 'string' && t === 'claude';

Try / catch

try {
  executor = ExecutorFactory.create({ type: 'shell', projectRoot });
} catch (e) {
  if (e.message.includes('not yet implemented')) {
    executor = ExecutorFactory.create({ type: 'claude', projectRoot });
  } else throw e;
}

Prevention

When it happens

Trigger: Calling ExecutorFactory.create({ type: 'shell', projectRoot }) (with or without config) — every such call throws unconditionally until the executor is implemented.

Common situations: Constructing an execution request with a hardcoded or config-driven executor type of 'shell'; following docs/examples that mention shell execution before the feature shipped; a user config file specifying shell as the preferred executor.

Related errors


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