decolua/9router · error · Error

Unknown tool: ${tool}

Error message

Unknown tool: ${tool}

What it means

addDNSEntry() looks up the tool name in the TOOL_HOSTS map to get the hosts entries to write to the system hosts file. If the tool key is absent, it throws `Unknown tool: ${tool}`. Only tools with defined host mappings are supported.

Source

Thrown at src/mitm/dns/dnsConfig.js:148

function checkAllDNSStatus() {
  try {
    const hostsContent = fs.readFileSync(HOSTS_FILE, "utf8");
    const result = {};
    for (const [tool, hosts] of Object.entries(TOOL_HOSTS)) {
      result[tool] = hosts.every(h => hostsContent.includes(h));
    }
    return result;
  } catch {
    return Object.fromEntries(Object.keys(TOOL_HOSTS).map(t => [t, false]));
  }
}

/**
 * Add DNS entries for a specific tool
 */
async function addDNSEntry(tool, sudoPassword) {
  const hosts = TOOL_HOSTS[tool];
  if (!hosts) throw new Error(`Unknown tool: ${tool}`);

  const entriesToAdd = hosts.filter(h => !checkDNSEntry(h));
  if (entriesToAdd.length === 0) {
    log(`🌐 DNS ${tool}: already active`);
    return;
  }

  try {
    if (IS_WIN) {
      // Read → trim → append → atomic write (Node-side, no CLI size limit)
      const current = fs.readFileSync(HOSTS_FILE, "utf8");
      const trimmed = current.replace(/[\r\n\s]+$/g, "");
      const toAppend = entriesToAdd.map(h => `127.0.0.1 ${h}`).join("\r\n");
      const next = `${trimmed}\r\n${toAppend}\r\n`;
      atomicWriteHostsWin(HOSTS_FILE, current, next);
      await runElevatedPowerShell("ipconfig /flushdns | Out-Null");
    } else {
      const current = fs.readFileSync(HOSTS_FILE, "utf8");

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Use an exact key from TOOL_HOSTS (check the exported map for valid names)
  2. Normalize the tool name (lowercase/trim) before calling addDNSEntry
  3. Add the new tool to TOOL_HOSTS if it is a legitimate new tool
  4. Guard the call with `if (TOOL_HOSTS[tool])` or equivalent validation

Example fix

// before
await addDNSEntry(toolName, sudoPassword);

// after
const key = String(toolName).trim().toLowerCase();
if (!(key in TOOL_HOSTS)) {
  throw new Error(`Unsupported tool: ${key}. Valid: ${Object.keys(TOOL_HOSTS).join(", ")}`);
}
await addDNSEntry(key, sudoPassword);
Defensive patterns

Strategy: validation

Validate before calling

import { TOOL_HOSTS } from './dnsConfig.js';
const key = String(tool).trim().toLowerCase();
if (!(key in TOOL_HOSTS)) {
  throw new Error(`Unknown tool "${key}". Supported: ${Object.keys(TOOL_HOSTS).join(", ")}`);
}
await addDNSEntry(key, sudoPassword);

Type guard

function isKnownTool(tool) {
  return typeof tool === 'string' && Object.prototype.hasOwnProperty.call(TOOL_HOSTS, tool.trim().toLowerCase());
}

Try / catch

try {
  await addDNSEntry(tool, sudoPassword);
} catch (e) {
  if (e.message.startsWith('Unknown tool:')) {
    console.error(`Invalid tool name. Valid keys: ${Object.keys(TOOL_HOSTS).join(', ')}`);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling addDNSEntry(tool, sudoPassword) with a tool name not present in TOOL_HOSTS: typo, wrong casing, new tool not yet mapped, or passing a display label instead of the registry key.

Common situations: Config file renamed a tool but DNS code uses the old key; user-supplied tool name passed through without validation; adding a new monitored tool without updating TOOL_HOSTS; case mismatch ('Claude' vs 'claude').

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/043d9469b312b1c7. Report an issue: GitHub.