affaan-m/ECC · error · Error
[ECC] ECC_DASHBOARD_HOST must be loopback-only (127.0.0.1…
Error message
[ECC] ECC_DASHBOARD_HOST must be loopback-only (127.0.0.1, localhost, or ::1).
What it means
resolveDashboardHost in scripts/dashboard-web.js enforces that the dashboard HTTP server binds only to loopback addresses. ECC_DASHBOARD_HOST set to anything other than 127.0.0.1, localhost, or ::1 throws, preventing accidental exposure of the dashboard to the network. This is a deliberate security-by-default measure.
Solutions
- Set ECC_DASHBOARD_HOST to 127.0.0.1, localhost, or ::1 (default 127.0.0.1 is used when unset).
- If remote access is needed, put a proper reverse proxy with auth in front of the loopback-bound server instead of rebinding.
- Check .env / shell exports for stray whitespace or casing and normalize the value.
Example fix
// before ECC_DASHBOARD_HOST=0.0.0.0 node scripts/dashboard-web.js // after ECC_DASHBOARD_HOST=127.0.0.1 node scripts/dashboard-web.js
Defensive patterns
Strategy: validation
Validate before calling
const host = (process.env.ECC_DASHBOARD_HOST || '').trim().toLowerCase();
if (host && !['127.0.0.1', 'localhost', '::1'].includes(host)) {
throw new Error(`ECC_DASHBOARD_HOST must be loopback, got: ${host}`);
} Type guard
function isLoopbackHost(v) { return ['127.0.0.1','localhost','::1','[::1]'].includes(String(v).trim().toLowerCase()); } Try / catch
try {
startDashboard();
} catch (e) {
if (e.message.includes('loopback-only')) {
console.error('Unset ECC_DASHBOARD_HOST or set it to 127.0.0.1 to use the dashboard locally.');
process.exit(1);
} else throw e;
} Prevention
- Never set ECC_DASHBOARD_HOST to 0.0.0.0 or a LAN IP; use a reverse proxy for remote access.
- Normalize env values (trim, lowercase) in deployment scripts.
- Document the loopback-only policy in onboarding/runbooks.
When it happens
Trigger: Setting ECC_DASHBOARD_HOST to a non-loopback value such as 0.0.0.0, a LAN IP (192.168.x.x), a hostname, or an uppercase/untrimmed variant that still fails the loopback set check.
Common situations: Trying to expose the dashboard in Docker or to a phone on the LAN by setting 0.0.0.0; CI setting the host to a container hostname; trailing spaces or capitalization quirks in env files.
Understand the failure class
Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.
Related errors
- artifact must be a resident regular file
- artifact path escapes output directory
- artifact path must be canonical and absolute
- artifact permits provider execution
- capsule.secret_canary
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/8c13ba3fc9ebb22c.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/dashboard-web.js:30
const fs = require('fs');
const path = require('path');
const http = require('http');
const {
LOOPBACK_HOSTNAMES,
buildAllowedHostnames,
isAllowedHostHeader,
isAllowedOrigin,
} = require('./lib/loopback-guard');
const { normalizeAgentTools } = require('./lib/agent-tools');
const { readHooksConfig } = require('./lib/hooks-config');
const DEFAULT_HOST = '127.0.0.1';
function resolveDashboardHost(env = process.env) {
const configured = String(env.ECC_DASHBOARD_HOST || '').trim().toLowerCase();
if (!configured) return DEFAULT_HOST;
if (!LOOPBACK_HOSTNAMES.has(configured)) {
throw new Error(
'[ECC] ECC_DASHBOARD_HOST must be loopback-only ' +
'(127.0.0.1, localhost, or ::1).'
);
}
return configured === '[::1]' ? '::1' : configured;
}
function parsePort(v) {
const n = parseInt(String(v), 10);
if (isNaN(n) || n < 1 || n > 65535) { console.error('[ECC] Invalid port: ' + v + ' — using 3456'); return 3456; }
return n;
}
const PORT = parsePort(process.argv[2] || process.env.ECC_DASHBOARD_PORT || '3456');
const HOST = resolveDashboardHost();
const ROOT = path.resolve(__dirname, '..');
function readFrontmatter(p) {
try {View on GitHub (pinned to 8321021c54)