{"record":{"id":"41142ce296fea0e7","repo":"garrytan/gstack","slug":"unknown-host-arg-valid-hosts-all-host-nam","errorCode":null,"errorMessage":"Unknown host '${arg}'. Valid hosts: ${ALL_HOST_NAMES.join(', ')}","messagePattern":"Unknown host '(.+?)'\\. Valid hosts: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"hosts/index.ts","lineNumber":56,"sourceCode":"    throw new Error(`Unknown host '${name}'. Valid hosts: ${ALL_HOST_NAMES.join(', ')}`);\n  }\n  return config;\n}\n\n/**\n * Resolve a host name from a CLI argument, handling aliases.\n * e.g., 'agents' → 'codex', 'droid' → 'factory'\n */\nexport function resolveHostArg(arg: string): string {\n  // Direct name match\n  if (HOST_CONFIG_MAP[arg]) return arg;\n\n  // Alias match\n  for (const config of ALL_HOST_CONFIGS) {\n    if (config.cliAliases?.includes(arg)) return config.name;\n  }\n\n  throw new Error(`Unknown host '${arg}'. Valid hosts: ${ALL_HOST_NAMES.join(', ')}`);\n}\n\n/**\n * Get hosts that are NOT the primary host (Claude).\n * These are the hosts that need generated skill docs.\n */\nexport function getExternalHosts(): HostConfig[] {\n  return ALL_HOST_CONFIGS.filter(c => c.name !== 'claude');\n}\n\n// Re-export individual configs for direct import\nexport { claude, codex, factory, kiro, opencode, slate, cursor, openclaw, hermes, gbrain };\n","sourceCodeStart":38,"sourceCodeEnd":69,"githubUrl":"https://github.com/garrytan/gstack/blob/94993f74012782fd94416dd44b8314f6363a13a4/hosts/index.ts#L38-L69","documentation":"Thrown by resolveHostArg() when a CLI argument matches neither a canonical host name in HOST_CONFIG_MAP nor any value in any host config's cliAliases array. It is the user-facing counterpart to 305: the CLI entry point canonicalizes free-text args, and anything unrecognized is rejected with the full valid-host list. Aliases (e.g. 'agents'→'codex', 'droid'→'factory') must be declared per-config via cliAliases.","triggerScenarios":"resolveHostArg(arg) where arg is misspelled, uppercase, an undeclared alias, or a host that does not exist. The function checks direct name match first, then iterates cliAliases; failing both throws.","commonSituations":"User types '--host Codex' (case) or '--host agent' (typo); an alias was intended but never added to the host config's cliAliases; a renamed host whose old name was not retained as an alias for back-compat.","solutions":["Use one of the names or aliases listed in the error message.","Check the casing — matching is case-sensitive.","If the alias should be valid, add it to the relevant host config's cliAliases array.","When renaming a host, keep the old name in cliAliases to avoid breaking existing scripts."],"exampleFix":"// before — undeclared alias\nresolveHostArg('robot'); // throws\n\n// after — add the alias in hosts/factory.ts (or similar)\nexport default { name: 'factory', cliAliases: ['droid', 'robot'], ... };","handlingStrategy":"validation","validationCode":"import { ALL_HOST_NAMES, HOST_CONFIG_MAP, ALL_HOST_CONFIGS } from './hosts';\nconst VALID_ARGS = new Set<string>([\n  ...ALL_HOST_NAMES,\n  ...ALL_HOST_CONFIGS.flatMap(c => c.cliAliases ?? []),\n]);\nfunction isValidHostArg(arg: string): boolean {\n  return VALID_ARGS.has(arg);\n}","typeGuard":"function isHostArg(arg: string): boolean {\n  if (HOST_CONFIG_MAP[arg]) return true;\n  return ALL_HOST_CONFIGS.some(c => c.cliAliases?.includes(arg));\n}","tryCatchPattern":"try {\n  return resolveHostArg(arg);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Unknown host')) {\n    // Suggest the closest match\n    const suggest = closestMatch(arg, ALL_HOST_NAMES);\n    throw new Error(`Unknown host '${arg}'. Did you mean '${suggest}'?`);\n  }\n  throw e;\n}","preventionTips":["Provide a --list-hosts CLI flag so users can discover valid values.","Keep deprecated host names as aliases to preserve back-compat.","Lowercase CLI input before resolving (names are lowercase).","Test every alias in the host registry's unit tests."],"tags":["cli","config","registry","host-config","validation"],"backgroundTag":null,"analyzedSha":"94993f74012782fd94416dd44b8314f6363a13a4","analyzedAt":"2026-08-12T04:06:23.140Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}