jackwener/OpenCLI · error · CommandExecutionError
Command ${fullName(cmd)} has no func or pipeline
Error message
Command ${fullName(cmd)} has no func or pipeline What it means
This CommandExecutionError is thrown by runCommand when a resolved CliCommand has neither a `func` nor a `pipeline` defined, so there is nothing to execute. The library treats this as an adapter-definition bug and asks the user to report it, since a properly registered command must always implement one of the two execution paths.
Source
Thrown at src/execution.ts:150
`Failed to load adapter module ${modulePath}: ${getErrorMessage(err)}`,
'Check that the adapter file exists and has no syntax errors.',
);
},
);
_loadedModules.set(modulePath, loadPromise);
}
await _loadedModules.get(modulePath);
const updated = getRegistry().get(fullName(cmd));
if (updated?.func) {
return runCommandFunc(updated, page, kwargs, debug);
}
if (updated?.pipeline) return executePipeline(page, updated.pipeline, { args: kwargs, debug });
}
if (cmd.func) return runCommandFunc(cmd, page, kwargs, debug);
if (cmd.pipeline) return executePipeline(page, cmd.pipeline, { args: kwargs, debug });
throw new CommandExecutionError(
`Command ${fullName(cmd)} has no func or pipeline`,
'This is likely a bug in the adapter definition. Please report this issue.',
);
}
function runCommandFunc(cmd: CliCommand, page: IPage | null, kwargs: CommandArgs, debug: boolean): Promise<unknown> {
if (cmd.browser === false) return cmd.func!(kwargs, debug);
if (!page) {
throw new CommandExecutionError(`Command ${fullName(cmd)} requires a browser session but none was provided`);
}
return (cmd as BrowserCliCommand).func!(page, kwargs, debug);
}
function resolvePreNav(cmd: CliCommand): string | null {
if (cmd.navigateBefore === false) return null;
if (typeof cmd.navigateBefore === 'string') return cmd.navigateBefore;
// strategy → navigateBefore expansion already happened in normalizeCommand().
return null;View on GitHub (pinned to 49907e53dc)
Solutions
- Open the adapter definition for the failing command (printed via fullName(cmd)) and add either a `func` implementation or a `pipeline`.
- If you cannot fix the adapter, report the issue to the adapter/library maintainer as the message suggests — this path is unreachable for well-formed definitions.
- Verify you are loading the intended adapter set: a stub or placeholder adapter may be shadowing the real command registration.
- Check for adapter/library version mismatches after upgrades and reinstall or align versions so the command resolves to a complete definition.
Example fix
// before
const deploy: CliCommand = { name: 'deploy', description: 'Deploy the app' }; // no func/pipeline
// after
const deploy: CliCommand = { name: 'deploy', description: 'Deploy the app', browser: false, func: async (kwargs, debug) => runDeploy(kwargs, debug) }; Defensive patterns
Strategy: type-guard
Validate before calling
function isExecutableCommand(cmd) {
return typeof cmd === 'object' && cmd !== null && (typeof cmd.func === 'function' || cmd.pipeline != null);
}
// before dispatch: if (!isExecutableCommand(cmd)) throw new Error(`Command ${cmd.name} is not executable`); Type guard
function hasFuncOrPipeline(cmd) {
return typeof (cmd as { func?: unknown }).func === 'function' || (cmd as { pipeline?: unknown }).pipeline != null;
} Try / catch
try {
await runCommand(cmd, page, kwargs, debug);
} catch (err) {
if (err instanceof CommandExecutionError && /has no func or pipeline/.test(err.message)) {
console.error(`Adapter bug in '${cmd.name}': define func or pipeline`);
}
throw err;
} Prevention
- Give every new adapter a func or pipeline before registering it.
- Add a startup assertion/CI check that scans registered commands for executability.
- Avoid `as CliCommand` casts that bypass type checking of func/pipeline presence.
- Test each command end-to-end so unreachable definitions surface in CI, not at runtime.
When it happens
Trigger: runTask or main resolves a command via kwargs and dispatches to runCommand, but the matching adapter object defines neither `func` nor `pipeline` (e.g. an adapter stub, a partially-migrated definition, or an object where both fields are undefined/removed).
Common situations: See trigger scenarios.
Related errors
- Not a git repository
- Working tree not clean: ${status}
- Stale .git/index.lock found — remove it first
- 12306 whoami failed: ${probe.detail}
- <train-no> "${trainNo}" does not look like a 12306 internal
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/5c00b88007ab664f.
Report an issue: GitHub.