projectdiscovery/nuclei · error

could not compile json: %s

Error message

could not compile json: %s

What it means

Template compilation error from Extractor.CompileExtractors (pkg/operators/extractors/compile.go:51). The json extractor's gojq query parses successfully but fails the gojq.Compile step, which type-checks the AST (function arity, unknown built-ins, invalid option usage).

Source

Thrown at pkg/operators/extractors/compile.go:51

		compiled, err := regexp.Compile(regex)
		if err != nil {
			return fmt.Errorf("could not compile regex: %s", regex)
		}
		_ = cache.Regex().Set(regex, compiled)
		e.regexCompiled = append(e.regexCompiled, compiled)
	}
	for i, kval := range e.KVal {
		e.KVal[i] = strings.ToLower(kval)
	}

	for _, query := range e.JSON {
		query, err := gojq.Parse(query)
		if err != nil {
			return fmt.Errorf("could not parse json: %s", query)
		}
		compiled, err := gojq.Compile(query)
		if err != nil {
			return fmt.Errorf("could not compile json: %s", query)
		}
		e.jsonCompiled = append(e.jsonCompiled, compiled)
	}

	for _, dslExp := range e.DSL {
		if cached, err := cache.DSL().GetIFPresent(dslExp); err == nil && cached != nil {
			e.dslCompiled = append(e.dslCompiled, cached)
			continue
		}
		compiled, err := govaluate.NewEvaluableExpressionWithFunctions(dslExp, dsl.HelperFunctions)
		if err != nil {
			return &dsl.CompilationError{DslSignature: dslExp, WrappedError: err}
		}
		_ = cache.DSL().Set(dslExp, compiled)
		e.dslCompiled = append(e.dslCompiled, compiled)
	}

	if e.CaseInsensitive {

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Simplify the query to well-supported core builtins (.x | .[0], //, | tostring, | tonumber, ltrimstr/1 etc.) and check arity
  2. Run the exact query through `gojq` at the version nuclei vendors to confirm it compiles
  3. Move complex transformation into a DSL extractor (type: dsl) where helper functions are richer
  4. Re-validate the template after upgrading nuclei/gojq versions

Example fix

# before (invalid arity)
json:
  - '.token | ltrimstr()'
# after
json:
  - '.token | ltrimstr("Bearer ")'
Defensive patterns

Strategy: validation

Validate before calling

for _, q := range ex.JSON {
	ast, err := gojq.Parse(q)
	if err != nil { return err }
	if _, err := gojq.Compile(ast); err != nil {
		return fmt.Errorf("query %q compiles-parse but fails gojq.Compile: %w", q, err)
	}
}

Type guard

func compilableGojq(q string) bool { ast, err := gojq.Parse(q); if err != nil { return false }; _, err = gojq.Compile(ast); return err == nil }

Try / catch

if err := ex.CompileExtractors(); err != nil && strings.Contains(err.Error(), "could not compile json") {
	// report unsupported builtin/arity; suggest DSL extractor for heavy transforms
}

Prevention

When it happens

Trigger: Queries calling a jq builtin gojq does not implement, wrong function arity (e.g. 'ltrimstr()' with no args or 'ascii_downcase(1)'), or invalid use of operators that parse but do not compile.

Common situations: Templates tested against a full jq build using rarely supported builtins or flags; version drift where the template was written for a newer gojq than the embedded nuclei version ships.

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/7688a19340d79fb7. Report an issue: GitHub.