vitessio/vitess · error

BUG: sqlparser emitted unknown type

Error message

BUG: sqlparser emitted unknown type

What it means

When compiling a CONVERT/CAST expression, the evalengine switches over the target type name sqlparser emitted (CHAR, SIGNED, UNSIGNED, DATE, etc.) and panics if the name is none of the known ones. The message asserts that sqlparser should never produce an unknown conversion type, so this panic indicates a bug in the parser-to-evalengine contract rather than bad user input.

Source

Thrown at go/vt/vtgate/evalengine/expr_convert.go:152

		return nil, nil
	case "DATE":
		if d := evalToDate(e, env.now, env.sqlmode.AllowZeroDate()); d != nil {
			return d, nil
		}
		return nil, nil
	case "TIME":
		p := ptr.Unwrap(c.Length, 0)
		if p > 6 {
			return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "Too-big precision %d specified for 'CONVERT'. Maximum is 6.", p)
		}
		if t := evalToTime(e, p); t != nil {
			return t, nil
		}
		return nil, nil
	case "YEAR":
		return nil, c.returnUnsupportedError()
	default:
		panic("BUG: sqlparser emitted unknown type")
	}
}

func (c *ConvertExpr) convertToBinaryType(tt sqltypes.Type) sqltypes.Type {
	if c.Length != nil {
		if *c.Length > 64*1024 {
			return sqltypes.Blob
		}
	} else if tt == sqltypes.Blob || tt == sqltypes.TypeJSON {
		return sqltypes.Blob
	}
	return sqltypes.VarBinary
}

func (c *ConvertExpr) convertToCharType(tt sqltypes.Type) sqltypes.Type {
	if c.Length != nil {
		col := colldata.Lookup(c.Collation)
		length := *c.Length * col.Charset().MaxWidth()

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Print the offending type name from the AST to identify the unhandled case
  2. Add a case for the new type in ConvertExpr's compile/convert switch in expr_convert.go
  3. Return a proper 'unsupported conversion' error (like the YEAR case does) instead of panicking for legitimately unsupported types
  4. Align sqlparser and evalengine versions

Example fix

// before
case "YEAR":
	return nil, c.returnUnsupportedError()
default:
	panic("BUG: sqlparser emitted unknown type")
// after
case "YEAR":
	return nil, c.returnUnsupportedError()
case "NEWTYPE":
	return convertNewType(...)
default:
	return nil, c.returnUnsupportedError() // or keep panic, but handle the new type
Defensive patterns

Strategy: validation

Validate before calling

// Validate CAST target types against known conversions before issuing the query
var castableTypes = map[string]bool{"CHAR": true, "SIGNED": true, "UNSIGNED": true, "DATE": true, "DATETIME": true, "TIME": true, "BINARY": true, "JSON": true, "DECIMAL": true, "FLOAT": true, "DOUBLE": true}
func isCastable(t string) bool { return castableTypes[strings.ToUpper(t)] }

Type guard

func isKnownConvertType(t sqlparser.ConvertType) bool {
	return isCastable(t.Type)
}

Try / catch

defer func() {
	if r := recover(); r != nil {
		err = fmt.Errorf("convert eval panic: %v", r)
	}
}()

Prevention

When it happens

Trigger: Evaluating a CAST/CONVERT whose target type string from the parsed AST does not match any case in ConvertExpr's switch — e.g., a newly added sqlparser convert type not yet handled, or a hand-built ConvertExpr with a typo'd type name.

Common situations: New MySQL cast types added to sqlparser (or Vitess version skew) where evalengine lags; tests constructing ConvertExpr manually; custom forks adding CAST types.

Related errors


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