nexu-io/open-design · error

vela login failed to start: ${result.error.message}

Error message

vela login failed to start: ${result.error.message}

What it means

Raised by waitForImmediateLoginFailure() when the vela login child emitted an 'error' event within the LOGIN_STARTUP_GRACE_MS window — i.e. the process failed to spawn or failed very early. result.error.message carries the underlying spawn error (ENOENT, EACCES, EAGAIN).

Source

Thrown at apps/daemon/src/integrations/vela.ts:1083

  capture: VelaLoginActivationCapture,
  terminal: Promise<VelaLoginChildTerminal>,
): Promise<void> {
  const result = await Promise.race<
    VelaLoginChildTerminal | { kind: 'running' }
  >([
    terminal,
    new Promise<{ kind: 'running' }>((resolve) => {
      const timer = setTimeout(
        () => resolve({ kind: 'running' }),
        LOGIN_STARTUP_GRACE_MS,
      );
      timer.unref?.();
    }),
  ]);

  if (result.kind === 'running') return;
  if (result.kind === 'error') {
    throw new Error(`vela login failed to start: ${result.error.message}`);
  }
  if (capture.activation.activationUrl) return;
  const detail = (capture.stderr || capture.stdout).trim();
  throw new Error(
    detail ||
      `vela login exited before authentication completed (code ${result.code ?? 'null'}, signal ${result.signal ?? 'null'})`,
  );
}

// Wait for the direct `vela login` attempt to either print its device-auth
// activation URL (healthy — the direct path works even on the transparent-proxy
// networks this fix targets, just possibly slowly) or exit/error BEFORE printing
// it (a real failure the caller can retry through the IPv4 proxy). Crucially, a
// merely slow-but-still-running direct login is NOT killed: once the grace
// elapses we simply stop blocking the request and let it keep running (the UI
// polls /status). Killing a slow-healthy direct login and re-routing it through
// the proxy is exactly the regression this avoids — on a corporate transparent
// proxy the proxy hop loses the client IP and the upstream 502s. Only an

View on GitHub (pinned to 5be4028344)

Solutions

  1. Inspect result.error.message: ENOENT → install vela or set VELA_BIN; EACCES → chmod +x the binary; EAGAIN → lower fd/memory pressure.
  2. Ensure the amr agent def resolves a real selectedPath via resolveAgentLaunch.
  3. If using the IPv4 proxy fallback path, the caller may still retry through it — make sure the fallback is enabled.

Example fix

// before
await waitForImmediateLoginFailure(capture, terminal);

// after
try {
  await waitForImmediateLoginFailure(capture, terminal);
} catch (err) {
  if (/ENOENT|EACCES/.test(String(err))) {
    // surface 'install vela or configure VELA_BIN' to the user, no retry
  }
  throw err;
}
Defensive patterns

Strategy: try-catch

Validate before calling

function isVelaBinPresent(bin = process.env.VELA_BIN): boolean {
  if (!bin) return false;
  try {
    // cheap existence check; real exec check happens at spawn
    return fs.statSync(bin).isFile();
  } catch {
    return false;
  }
}

Type guard

function isSpawnFailureMessage(err: unknown): boolean {
  return err instanceof Error && err.message.startsWith('vela login failed to start:');
}

function underlyingErrno(err: unknown): string | null {
  const m = err instanceof Error ? err.message.match(/\b(ENOENT|EACCES|EAGAIN)\b/) : null;
  return m ? m[1] : null;
}

Try / catch

try {
  await waitForImmediateLoginFailure(capture, terminal);
} catch (err) {
  const errno = underlyingErrno(err);
  if (errno === 'ENOENT' || errno === 'EACCES') {
    // permanent — surface 'install vela or configure VELA_BIN', do not retry
  }
  throw err;
}

Prevention

When it happens

Trigger: Spawn errors before the grace timer elapses: binary missing (ENOENT), not executable (EACCES), or OS resource limits (EAGAIN). The direct login attempt fails before it can print a device-auth activation URL.

Common situations: VELA_BIN points at a non-existent path; vela not on PATH; binary exists but lacks execute permission; /tmp or process env in a broken state; packaged daemon lost access to the bundled binary.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/788588785e041476. Report an issue: GitHub.