vitessio/vitess · error

IntervalDateExpr.Unit is not set

Error message

IntervalDateExpr.Unit is not set

What it means

IntervalDateExpr.NormalizedUnit() panics when the interval unit field is zero (IntervalNone) while the expression's syntax variant (e.g. plain INTERVAL expr in DATE_ADD/DATE_SUB) requires an explicit unit. The library cannot infer a default unit for this syntax, so it treats the AST as malformed and panics instead of returning an error.

Source

Thrown at go/vt/sqlparser/ast_funcs.go:2849

}

func (node *IntervalDateExpr) IsSubtraction() bool {
	switch node.Syntax {
	case IntervalDateExprDateAdd, IntervalDateExprAdddate, IntervalDateExprBinaryAdd, IntervalDateExprBinaryAddLeft, IntervalDateExprTimestampadd:
		return false
	case IntervalDateExprDateSub, IntervalDateExprSubdate, IntervalDateExprBinarySub:
		return true
	default:
		panic("invalid IntervalDateExpr syntax")
	}
}

func (node *IntervalDateExpr) NormalizedUnit() IntervalType {
	if node.Unit == IntervalNone {
		if node.Syntax == IntervalDateExprAdddate || node.Syntax == IntervalDateExprSubdate {
			return IntervalDay
		}
		panic("IntervalDateExpr.Unit is not set")
	}
	return node.Unit
}

func (node *IntervalDateExpr) FnName() string {
	switch node.Syntax {
	case IntervalDateExprDateAdd:
		return "date_add"
	case IntervalDateExprDateSub:
		return "date_sub"
	case IntervalDateExprAdddate:
		return "adddate"
	case IntervalDateExprSubdate:
		return "subdate"
	case IntervalDateExprTimestampadd:
		return "timestampadd"
	case IntervalDateExprBinaryAdd, IntervalDateExprBinaryAddLeft:
		return "<arithmetic interval addition>"

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Ensure Unit is explicitly set to a valid IntervalType (e.g. IntervalDay) whenever you construct an IntervalDateExpr whose syntax is not Adddate/Subdate
  2. If your AST rewrite replaces an IntervalExpr, copy Unit from the original node instead of creating a bare IntervalDateExpr
  3. Parse the SQL with the parser (which always sets Unit) rather than fabricating nodes by hand
  4. If you believe a default unit should apply for your syntax variant, add the case to NormalizedUnit() and regenerate

Example fix

// before
node := &sqlparser.IntervalDateExpr{Syntax: sqlparser.IntervalDateExprDateAdd}
_ = node.NormalizedUnit() // panics: Unit is not set
// after
node := &sqlparser.IntervalDateExpr{Syntax: sqlparser.IntervalDateExprDateAdd, Unit: sqlparser.IntervalDay}
_ = node.NormalizedUnit()
Defensive patterns

Strategy: validation

Validate before calling

func safeNormalizedUnit(n *sqlparser.IntervalDateExpr) (sqlparser.IntervalType, error) {
    if n.Unit == sqlparser.IntervalNone {
        if n.Syntax != sqlparser.IntervalDateExprAdddate && n.Syntax != sqlparser.IntervalDateExprSubdate {
            return 0, errors.New("IntervalDateExpr.Unit is not set")
        }
    }
    return n.NormalizedUnit(), nil
}

Try / catch

// Go: wrap the call so a panic does not take down the process
func normalizedUnitSafe(n *sqlparser.IntervalDateExpr) (u sqlparser.IntervalType, err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("interval unit panic: %v", r)
        }
    }()
    return n.NormalizedUnit(), nil
}

Prevention

When it happens

Trigger: Constructing an IntervalDateExpr manually with Syntax set to a form that requires a unit (not IntervalDateExprAdddate/IntervalDateExprSubdate) while leaving Unit as IntervalNone, then calling NormalizedUnit() (directly or via date-expression formatting/normalization passes in the sqlparser).

Common situations: Hand-built AST nodes in tests or rewriting tools; an upstream code generator or AST transformation that copies a date expression but forgets to populate Unit; parser upgrades where new syntax variants were added but Unit defaults were not propagated.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/e8246a33a231f64a. Report an issue: GitHub.