projectdiscovery/katana · error
expression eval panic: %v
Error message
expression eval panic: %v
What it means
safeEvalExpr wraps dsl engine.EvalExpr with a recover() because the govaluate evaluation engine can panic on inputs that aren't valid expressions — most commonly plain strings treated as references to undefined variables. Instead of crashing, the panic is converted into this error and returned to the form-filling resolver.
Source
Thrown at pkg/utils/formfill.go:80
}
engine := getFormDSLEngine()
if engine == nil {
return value
}
result, err := safeEvalExpr(engine, value)
if err != nil {
return value
}
return fmt.Sprintf("%v", result)
}
// safeEvalExpr wraps engine.EvalExpr with panic recovery since the
// underlying govaluate library can panic on inputs that aren't
// valid expressions (e.g. plain strings treated as undefined variables).
func safeEvalExpr(engine *dsl.Engine, expr string) (result interface{}, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("expression eval panic: %v", r)
}
}()
return engine.EvalExpr(expr, map[string]interface{}{})
}
// Resolve evaluates all fields through the DSL engine, resolving any
// helper function calls like rand_email() or rand_password(8, true).
// Plain string values pass through unchanged.
func (f *FormFillData) Resolve() {
f.Email = resolveField(f.Email)
f.Color = resolveField(f.Color)
f.Password = resolveField(f.Password)
f.PhoneNumber = resolveField(f.PhoneNumber)
f.Placeholder = resolveField(f.Placeholder)
}
// FormInput is an input for a form field
type FormInput struct {View on GitHub (pinned to e3e742739c)
Solutions
- Quote/escape the value before evaluation, or bypass the DSL for values that are plain literals (pass them straight through).
- Check the %v panic message to identify the offending expression and fix the field's value in your form-fill config.
- Upgrade the govaluate dependency if a newer version handles the failing input without panicking.
- Pre-validate values with a regex for expression metacharacters and mark them as literals.
Example fix
// before
result, err := safeEvalExpr(engine, fieldValue) // panics on "O'Brien (work)"
// after
var result interface{}
var err error
if isPlainLiteral(fieldValue) {
result = fieldValue
} else {
result, err = safeEvalExpr(engine, fieldValue)
} Defensive patterns
Strategy: try-catch
Validate before calling
// treat values containing expression metacharacters as literals
var exprMeta = regexp.MustCompile(`[()&|!<>="']`)
func needsLiteral(v string) bool { return exprMeta.MatchString(v) } Type guard
func isSafeExpression(s string) bool {
// a safe expression references only known variables and operators
return exprMeta.MatchString(s) == false || isQuotedString(s)
} Try / catch
result, err := safeEvalExpr(engine, expr)
if err != nil {
if strings.HasPrefix(err.Error(), "expression eval panic") {
log.Printf("non-expression value %q, using as literal", expr)
result = expr
err = nil
}
} Prevention
- Route plain-literal field values around the DSL engine entirely.
- Keep the govaluate dependency updated for panic fixes on edge-case inputs.
- Unit-test Resolve with realistic page strings containing quotes, apostrophes, and operators.
When it happens
Trigger: Calling Resolve on form fields whose value expression is a literal string containing characters govaluate treats as expression syntax (quotes, operators, parentheses), causing engine.EvalExpr to panic internally and safeEvalExpr to recover and return "expression eval panic: %v".
Common situations: Auto-filling forms where the field value comes from arbitrary page data or user config; a value like "O'Brien (work)" or "a && b" interpreted as an expression instead of literal text; missing DSL escaping when values are meant to be plain strings.
Related errors
AI-assisted analysis of projectdiscovery/katana@e3e742739c (2026-09-03).
Data as JSON: /api/errors/1bd89492d1853569.
Report an issue: GitHub.