crowdsecurity/crowdsec · error

while find scenario asserts

Error message

while find scenario asserts: %w

What it means

GetScenariosCoverage globs <hubDir>/.tests/*/scenario.assert files; a malformed glob pattern aborts with 'while find scenario asserts: <err>'. Same ErrBadPattern failure mode as the parser coverage path, applied to scenario asserts.

Solutions

  1. Remove or escape glob metacharacters in the hubDir path (filepath.Escape)
  2. Rename the directory to one without '[', ']', '?', '*'
  3. Pass a plain absolute literal path as hubDir

Example fix

// before
GetScenariosCoverage("/tmp/hub[test]", ...)
// after
GetScenariosCoverage(filepath.Escape("/tmp/hub[test]"), ...)
Defensive patterns

Strategy: validation

Validate before calling

if strings.ContainsAny(hubDir, "[]*?") {
    hubDir = filepath.Escape(hubDir)
}
if _, err := filepath.Glob(filepath.Join(hubDir, ".tests", "*", "scenario.assert")); err != nil {
    return err
}

Try / catch

cov, err := hubtest.GetScenariosCoverage(hubDir, ...)
if err != nil {
    if strings.Contains(err.Error(), "syntax error in pattern") { /* sanitize hubDir and retry */ }
}

Prevention

When it happens

Trigger: Calling GetScenariosCoverage(hubDir, ...) when hubDir (or the joined pattern) contains unbalanced glob metacharacters such as '[' causing filepath.Glob to return ErrBadPattern.

Common situations: Hub directory path containing bracketed or wildcard characters (sandbox/test dir names like 'dir[0]'); hubDir accidentally containing a glob expression instead of a literal path.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


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

Appendix: source

Thrown at pkg/hubtest/coverage.go:196

		return nil, errors.New("no scenarios in hub index")
	}

	// populate from hub, iterate in alphabetical order
	pkeys := maptools.SortedKeys(h.HubIndex.GetItemMap(cwhub.SCENARIOS))
	coverage := make([]Coverage, len(pkeys))

	for i, name := range pkeys {
		coverage[i] = Coverage{
			Name:       name,
			TestsCount: 0,
			PresentIn:  make(map[string]bool),
		}
	}

	// parser the expressions a-la-oneagain
	passerts, err := filepath.Glob(filepath.Join(hubDir, ".tests", "*", "scenario.assert"))
	if err != nil {
		return nil, fmt.Errorf("while find scenario asserts: %w", err)
	}

	for _, assert := range passerts {
		file, err := os.Open(assert)
		if err != nil {
			return nil, fmt.Errorf("while reading %s: %w", assert, err)
		}

		scanner := bufio.NewScanner(file)
		for scanner.Scan() {
			line := scanner.Text()
			log.Debugf("assert line : %s", line)
			match := scenarioResultRE.FindStringSubmatch(line)

			if len(match) == 0 {
				log.Debugf("%s doesn't match", line)
				continue
			}

View on GitHub (pinned to 909b515798)