garrytan/gstack · error
Unknown host '${name}'. Valid hosts: ${ALL_HOST_NAMES.join('
Error message
Unknown host '${name}'. Valid hosts: ${ALL_HOST_NAMES.join(', ')} What it means
Thrown by getHostConfig() when the requested host name has no entry in the HOST_CONFIG_MAP registry built from ALL_HOST_CONFIGS. It is a fail-closed lookup: the function promises a HostConfig and refuses to return undefined, listing every registered host name in the message so the caller can self-correct. Adding a host requires both a config file and registration in hosts/index.ts.
Source
Thrown at hosts/index.ts:38
/** All registered host configs. Add new hosts here. */
export const ALL_HOST_CONFIGS: HostConfig[] = [claude, codex, factory, kiro, opencode, slate, cursor, openclaw, hermes, gbrain];
/** Map from host name to config. */
export const HOST_CONFIG_MAP: Record<string, HostConfig> = Object.fromEntries(
ALL_HOST_CONFIGS.map(c => [c.name, c])
);
/** Union type of all host names, derived from configs. */
export type Host = (typeof ALL_HOST_CONFIGS)[number]['name'];
/** All host names as a string array (for CLI arg validation, etc.). */
export const ALL_HOST_NAMES: string[] = ALL_HOST_CONFIGS.map(c => c.name);
/** Get a host config by name. Throws if not found. */
export function getHostConfig(name: string): HostConfig {
const config = HOST_CONFIG_MAP[name];
if (!config) {
throw new Error(`Unknown host '${name}'. Valid hosts: ${ALL_HOST_NAMES.join(', ')}`);
}
return config;
}
/**
* Resolve a host name from a CLI argument, handling aliases.
* e.g., 'agents' → 'codex', 'droid' → 'factory'
*/
export function resolveHostArg(arg: string): string {
// Direct name match
if (HOST_CONFIG_MAP[arg]) return arg;
// Alias match
for (const config of ALL_HOST_CONFIGS) {
if (config.cliAliases?.includes(arg)) return config.name;
}
throw new Error(`Unknown host '${arg}'. Valid hosts: ${ALL_HOST_NAMES.join(', ')}`);View on GitHub (pinned to 94993f7401)
Solutions
- Use the comma-separated list in the error message to pick the exact canonical name.
- For aliases like 'agents' or 'droid', call resolveHostArg() first to canonicalize before getHostConfig().
- If adding a new host, import its config and append it to ALL_HOST_CONFIGS in hosts/index.ts.
- Lowercase the input if case is the issue — names are stored lowercase.
Example fix
// before — alias passed to getHostConfig throws
const cfg = getHostConfig('agents');
// after — resolve alias to canonical name first
const cfg = getHostConfig(resolveHostArg('agents')); // → codex Defensive patterns
Strategy: validation
Validate before calling
import { ALL_HOST_NAMES, HOST_CONFIG_MAP } from './hosts';
function assertHostKnown(name: string): void {
if (!HOST_CONFIG_MAP[name]) {
throw new Error(`'${name}' is not registered. Known: ${ALL_HOST_NAMES.join(', ')}`);
}
} Type guard
import { ALL_HOST_NAMES } from './hosts';
const HOST_NAME_SET = new Set(ALL_HOST_NAMES);
function isHostName(name: string): boolean {
return typeof name === 'string' && HOST_NAME_SET.has(name);
} Try / catch
try {
return getHostConfig(name);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Unknown host')) {
return getHostConfig(resolveHostArg(name.toLowerCase())); // try alias
}
throw e;
} Prevention
- Always resolve CLI args through resolveHostArg before getHostConfig.
- Use the Host union type, not string, for host-name parameters so the compiler rejects unknowns.
- When adding a host, update ALL_HOST_CONFIGS and re-export in the same commit.
- Add a unit test asserting every alias resolves to a known host.
When it happens
Trigger: Call getHostConfig(name) where name is undefined, misspelled, differently-cased, or genuinely not in the registry (e.g. a host whose config file exists but was never imported into ALL_HOST_CONFIGS). Case-sensitive: 'Claude' will not match 'claude'.
Common situations: Typo in a CLI flag or config value; a new host was added as a file but the author forgot to append it to ALL_HOST_CONFIGS; passing a host alias (e.g. 'agents') to getHostConfig instead of resolveHostArg; case mismatch.
Related errors
- Unknown host '${arg}'. Valid hosts: ${ALL_HOST_NAMES.join(',
- Unsafe value for ${context}: ${val}
- Skill name is empty.
- Invalid skill name "${name}". Must be lowercase letters/digi
- stageSkill: files map is empty.
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/24b90f753b8bf68e.
Report an issue: GitHub.