crowdsecurity/crowdsec · error

appsec is down: %w

Error message

appsec is down: %w

What it means

After starting the crowdsec daemon, RunWithNucleiTemplate polls IsAlive against the AppSec host; if the AppSec component never becomes reachable the daemon's log file is dumped and this error is returned. It means the AppSec engine failed to start or bind in time.

Source

Thrown at pkg/hubtest/hubtest_item.go:385

	crowdsecDaemon := exec.CommandContext(ctx, t.CrowdSecPath, cmdArgs...)
	crowdsecDaemon.Dir = testPath
	crowdsecDaemon.Env = []string{"TESTDIR=" + testPath, "DATADIR=" + t.RuntimeHubConfig.InstallDataDir, "TZ=UTC"}

	if err := crowdsecDaemon.Start(); err != nil {
		return fmt.Errorf("starting crowdsec daemon: %w", err)
	}

	// wait for the appsec port to be available
	if _, err = IsAlive(ctx, t.AppSecHost); err != nil {
		crowdsecLog, err2 := os.ReadFile(crowdsecLogFile)
		if err2 != nil {
			log.Errorf("unable to read crowdsec log file '%s': %s", crowdsecLogFile, err)
		} else {
			log.Errorf("crowdsec log file '%s'", crowdsecLogFile)
			log.Errorf("%s\n", string(crowdsecLog))
		}

		return fmt.Errorf("appsec is down: %w", err)
	}

	// check if the target is available
	nucleiTargetParsedURL, err := url.Parse(t.NucleiTargetHost)
	if err != nil {
		return fmt.Errorf("unable to parse target '%s': %w", t.NucleiTargetHost, err)
	}

	nucleiTargetHost := nucleiTargetParsedURL.Host
	if _, err = IsAlive(ctx, nucleiTargetHost); err != nil {
		return fmt.Errorf("target is down: %w", err)
	}

	nucleiConfig := NucleiConfig{
		Path:      "nuclei",
		OutputDir: t.RuntimePath,
		CmdLineOptions: []string{
			"-ev",    // allow variables from environment

View on GitHub (pinned to 909b515798)

Solutions

  1. Read the printed crowdsec log file content in the error output — it shows why crowdsec/appsec died
  2. Kill leftover crowdsec processes from previous test runs holding the appsec port
  3. Verify the test config enables appsec and matches t.AppSecHost (host:port)
  4. Confirm appsec rules were installed (installAppsecRuleItem ran) before starting the daemon
Defensive patterns

Strategy: retry

Validate before calling

if err := waitReachable(appsecHost, 30*time.Second); err != nil { t.Skipf("appsec never came up: %v", err) }

Try / catch

if err := test.Run(ctx); err != nil {
	if strings.Contains(err.Error(), "appsec is down") {
		log.Printf("dump crowdsec.log and config for diagnosis: %v", err)
	}
}

Prevention

When it happens

Trigger: IsAlive(ctx, t.AppSecHost) times out or errors after crowdsec starts: appsec not enabled in the test config, wrong port in appsec config, crowdsec crashed at startup, or slow startup exceeding the poll deadline.

Common situations: Port already in use by a leftover daemon from a previous run; appsec_configs/appsec rules not installed in the test DATADIR; config pointing appsec at a different address than AppSecHost; crowdsec panic visible in the dumped crowdsec.log.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/e3b75b725de23bb8. Report an issue: GitHub.