crowdsecurity/crowdsec · error

esbuild returned no output files

Error message

esbuild returned no output files

What it means

In the obfuscate command, buildObfuscatorBundle runs esbuild with write:false to produce the obfuscator bundle in memory; if esbuild succeeds with no errors but returns zero output files, there is nothing to return and the function fails with this error. Like error 224 it is an internal invariant: a successful in-memory build should always yield OutputFiles.

Source

Thrown at pkg/appsec/challenge/js/cmd/obfuscate/main.go:79

func buildObfuscatorBundle() ([]byte, error) {
	result := esbuildapi.Build(esbuildapi.BuildOptions{
		EntryPoints: []string{entryPoint},
		Bundle:      true,
		Write:       false,
		Format:      esbuildapi.FormatIIFE,
		Platform:    esbuildapi.PlatformBrowser,
		Target:      esbuildapi.ES2022,
		Sourcemap:   esbuildapi.SourceMapNone,
		// JS obfuscator expects window/global to be available, but in WASM we don't have them, so we alias them to globalThis
		Banner: map[string]string{"js": "var self=globalThis; var window=globalThis; var global=globalThis;"},
	})

	if len(result.Errors) > 0 {
		return nil, fmt.Errorf("esbuild failed with %d error(s): %s", len(result.Errors), result.Errors[0].Text)
	}
	if len(result.OutputFiles) == 0 {
		return nil, errors.New("esbuild returned no output files")
	}

	return result.OutputFiles[0].Contents, nil
}

func computeBuildKey(bundleData []byte) (string, error) {
	out, err := exec.CommandContext(context.Background(), "javy", "--version").Output()
	if err != nil {
		return "", fmt.Errorf("failed to run 'javy --version' (is javy in PATH?): %w", err)
	}

	return fmt.Sprintf("bundle-sha256=%x %s", sha256.Sum256(bundleData), strings.TrimSpace(string(out))), nil
}

// currentBuildKey returns the build key recorded in the existing wasm.gz
// header, or "" if the file is missing or unreadable.
func currentBuildKey() string {
	f, err := os.Open(wasmGzFile)

View on GitHub (pinned to 909b515798)

Solutions

  1. Verify esbuild build options include correct entryPoints, bundle:true and write:false so OutputFiles is populated.
  2. Check for plugins/loaders that intercept and drop output files.
  3. Compare the esbuild library version against the one used when the tool last worked; adjust the API usage.
  4. Add debug logging of build options and result metadata when this fires.

Example fix

// before
if len(result.OutputFiles) == 0 {
    return nil, errors.New("esbuild returned no output files")
}
// after: include build context in the failure
if len(result.OutputFiles) == 0 {
    return nil, fmt.Errorf("esbuild returned no output files (entry=%v)", opts.EntryPoints)
}
Defensive patterns

Strategy: validation

Validate before calling

if len(opts.EntryPoints) == 0 {
    return nil, errors.New("buildObfuscatorBundle: no entryPoints configured")
}

Try / catch

result, err := api.Build(opts)
if err != nil { return nil, err }
if len(result.OutputFiles) == 0 {
    return nil, fmt.Errorf("esbuild returned no output files (entry=%v)", opts.EntryPoints)
}
return result.OutputFiles[0].Contents, nil

Prevention

When it happens

Trigger: esbuild build with write:false completes cleanly but result.OutputFiles is empty in buildObfuscatorBundle, called from main.

Common situations: Missing or misconfigured outfile/entryPoints options; esbuild version differences in OutputFiles behavior; a custom plugin suppressing output; wrong bundle options that make the build a no-op.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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