ruvnet/ruflo · error
Refusing to probe non-loopback Meta-Proxy bind "${bind}".
Error message
Refusing to probe non-loopback Meta-Proxy bind "${bind}". What it means
effectiveEndpoint() reads the Meta-Proxy config file's `bind` value (defaulting to 127.0.0.1:11435) before probing the daemon. If the configured bind address is not a loopback address, the library refuses to probe it, because probing (and later signaling) a proxy listening on a non-loopback interface could affect other machines' daemons. This is a deliberate safety guard in the library, not a network failure.
Source
Thrown at v3/@claude-flow/cli/src/proxy/activation.ts:33
} from './paths.js';
export interface EffectiveProxy { version: string; pid: number; executable: string; }
type Wait = (milliseconds: number) => Promise<void>;
const waitNormally: Wait = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
function processExists(pid: number): boolean {
try { process.kill(pid, 0); return true; } catch (error) {
return (error as NodeJS.ErrnoException).code === 'EPERM';
}
}
function effectiveEndpoint(): string {
let bind = '127.0.0.1:11435';
try {
const match = fs.readFileSync(proxyConfigPath(), 'utf8').match(/^bind\s*=\s*"([^"]+)"\s*$/m);
if (match?.[1]) bind = match[1];
} catch { /* documented default */ }
if (!isLoopbackBind(bind)) throw new Error(`Refusing to probe non-loopback Meta-Proxy bind "${bind}".`);
return `http://${bind}`;
}
function executableFor(pid: number, platform: NodeJS.Platform): string | null {
try {
if (platform === 'linux') {
const result = spawnSync('readlink', ['-f', `/proc/${pid}/exe`], { encoding: 'utf8', timeout: 2_000 });
return result.status === 0 ? result.stdout.trim() || null : null;
}
if (platform === 'win32') {
const command = `$p = Get-CimInstance Win32_Process -Filter 'ProcessId = ${pid}'; if ($null -ne $p) { [Console]::Out.Write($p.ExecutablePath) }`;
const result = spawnSync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', command], { encoding: 'utf8', timeout: 2_000, windowsHide: true });
return result.status === 0 ? result.stdout.trim() || null : null;
}
const result = spawnSync('ps', ['-p', String(pid), '-o', 'comm='], { encoding: 'utf8', timeout: 2_000 });
return result.status === 0 ? result.stdout.trim() || null : null;
} catch { return null; }
}View on GitHub (pinned to 29f048fc3b)
Solutions
- Edit the Meta-Proxy config file (see proxyConfigPath(), typically under ~/.metaharness) and set bind to a loopback address, e.g. bind = "127.0.0.1:11435"
- If you intentionally need a non-loopback bind, run/probe the daemon yourself outside this library's activation flow; the CLI will not probe non-loopback endpoints by design
- Remove the bind line entirely to fall back to the documented default 127.0.0.1:11435
- Verify the parsed value is loopback before activating: node -e "console.log(require('net').isLoopback?.(...) )" or check the address manually
Example fix
// before (proxy config) bind = "0.0.0.0:11435" // after bind = "127.0.0.1:11435"
Defensive patterns
Strategy: validation
Validate before calling
import fs from 'node:fs';
// Read the same bind the library will use and reject non-loopback before calling.
const cfg = fs.readFileSync(proxyConfigPath(), 'utf8');
const bind = cfg.match(/^bind\s*=\s*"([^"]+)"\s*$/m)?.[1] ?? '127.0.0.1:11435';
const host = bind.split(':')[0];
if (!(host === 'localhost' || host === '127.0.0.1' || host === '::1' || host === '[::1]')) {
throw new Error(`Fix bind in proxy config first: "${bind}" is not loopback`);
}
await installAndActivateProxy(version); Type guard
function isLoopbackBind(bind: string): boolean {
const host = bind.replace(/^\[|\]$/g, '').split(':')[0];
return host === 'localhost' || host === '127.0.0.1' || host === '::1' || host.endsWith('.127.0.0.1') || /^127\./.test(host);
} Try / catch
null
Prevention
- Keep bind on 127.0.0.1:11435 unless you deliberately manage remote access yourself
- Lint/validate the proxy config in CI before running proxy activation
- Never copy server-oriented configs (0.0.0.0 binds) into your local Meta-Harness config
- If you need remote reach, front the loopback proxy with your own reverse proxy
When it happens
Trigger: Calling any function that resolves the effective endpoint (probeEffectiveProxy, installAndActivateProxy via stopEffective/launchAndVerify) while proxyConfigPath()'s config contains a `bind = "..."` line whose value is not loopback (e.g. "0.0.0.0:11435", "192.168.1.10:11435", a hostname, or a non-loopback IP).
Common situations: Users edit the Meta-Proxy config to expose the proxy on a LAN address or all interfaces so other hosts/containers can reach it; Docker/Kubernetes setups binding 0.0.0.0; copy-pasted config from a remote-server guide; a stale config left by a manual daemon setup.
Related errors
- unknown game "${key}". Known: ${Object.keys(GAMES).join(', '
- unknown strategy "${name}". Available: ${roster.map((r) => r
- signBacktestArtifact: privateKey must be 32 bytes (got ${pri
- Dangerous key segment rejected: ${part}
- localCompute: no adapter for graphId=${input.graphId}
AI-assisted analysis of ruvnet/ruflo@29f048fc3b (2026-09-01).
Data as JSON: /api/errors/17604dc3d3da10f3.
Report an issue: GitHub.