{"record":{"id":"e8246a33a231f64a","repo":"vitessio/vitess","slug":"intervaldateexpr-unit-is-not-set","errorCode":null,"errorMessage":"IntervalDateExpr.Unit is not set","messagePattern":"IntervalDateExpr\\.Unit is not set","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/sqlparser/ast_funcs.go","lineNumber":2849,"sourceCode":"}\n\nfunc (node *IntervalDateExpr) IsSubtraction() bool {\n\tswitch node.Syntax {\n\tcase IntervalDateExprDateAdd, IntervalDateExprAdddate, IntervalDateExprBinaryAdd, IntervalDateExprBinaryAddLeft, IntervalDateExprTimestampadd:\n\t\treturn false\n\tcase IntervalDateExprDateSub, IntervalDateExprSubdate, IntervalDateExprBinarySub:\n\t\treturn true\n\tdefault:\n\t\tpanic(\"invalid IntervalDateExpr syntax\")\n\t}\n}\n\nfunc (node *IntervalDateExpr) NormalizedUnit() IntervalType {\n\tif node.Unit == IntervalNone {\n\t\tif node.Syntax == IntervalDateExprAdddate || node.Syntax == IntervalDateExprSubdate {\n\t\t\treturn IntervalDay\n\t\t}\n\t\tpanic(\"IntervalDateExpr.Unit is not set\")\n\t}\n\treturn node.Unit\n}\n\nfunc (node *IntervalDateExpr) FnName() string {\n\tswitch node.Syntax {\n\tcase IntervalDateExprDateAdd:\n\t\treturn \"date_add\"\n\tcase IntervalDateExprDateSub:\n\t\treturn \"date_sub\"\n\tcase IntervalDateExprAdddate:\n\t\treturn \"adddate\"\n\tcase IntervalDateExprSubdate:\n\t\treturn \"subdate\"\n\tcase IntervalDateExprTimestampadd:\n\t\treturn \"timestampadd\"\n\tcase IntervalDateExprBinaryAdd, IntervalDateExprBinaryAddLeft:\n\t\treturn \"<arithmetic interval addition>\"","sourceCodeStart":2831,"sourceCodeEnd":2867,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/sqlparser/ast_funcs.go#L2831-L2867","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Ensure Unit is explicitly set to a valid IntervalType (e.g. IntervalDay) whenever you construct an IntervalDateExpr whose syntax is not Adddate/Subdate","If your AST rewrite replaces an IntervalExpr, copy Unit from the original node instead of creating a bare IntervalDateExpr","Parse the SQL with the parser (which always sets Unit) rather than fabricating nodes by hand","If you believe a default unit should apply for your syntax variant, add the case to NormalizedUnit() and regenerate"],"exampleFix":"// before\nnode := &sqlparser.IntervalDateExpr{Syntax: sqlparser.IntervalDateExprDateAdd}\n_ = node.NormalizedUnit() // panics: Unit is not set\n// after\nnode := &sqlparser.IntervalDateExpr{Syntax: sqlparser.IntervalDateExprDateAdd, Unit: sqlparser.IntervalDay}\n_ = node.NormalizedUnit()","handlingStrategy":"validation","validationCode":"func safeNormalizedUnit(n *sqlparser.IntervalDateExpr) (sqlparser.IntervalType, error) {\n    if n.Unit == sqlparser.IntervalNone {\n        if n.Syntax != sqlparser.IntervalDateExprAdddate && n.Syntax != sqlparser.IntervalDateExprSubdate {\n            return 0, errors.New(\"IntervalDateExpr.Unit is not set\")\n        }\n    }\n    return n.NormalizedUnit(), nil\n}","typeGuard":null,"tryCatchPattern":"// Go: wrap the call so a panic does not take down the process\nfunc normalizedUnitSafe(n *sqlparser.IntervalDateExpr) (u sqlparser.IntervalType, err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            err = fmt.Errorf(\"interval unit panic: %v\", r)\n        }\n    }()\n    return n.NormalizedUnit(), nil\n}","preventionTips":["Always set Unit when constructing IntervalDateExpr unless syntax is Adddate/Subdate","Copy Unit from source nodes in AST rewrites","Prefer parser-produced nodes over hand-built ones","Add a constructor helper that enforces Unit is non-zero"],"tags":["sqlparser","ast","panic","bug"],"backgroundTag":"ast-node-misconstructed","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}