vitessio/vitess · critical
TypedCollation should fit in an int32
Error message
TypedCollation should fit in an int32
What it means
An init() guard in go/mysql/collations panics if the TypedCollation struct is not exactly 4 bytes on the current platform. TypedCollation must fit in an int32 because it is passed/stored as a 32-bit value across API boundaries; a layout change would silently corrupt those paths.
Source
Thrown at go/mysql/collations/coercion.go:26
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package collations
import (
"fmt"
"unsafe"
)
func init() {
if unsafe.Sizeof(TypedCollation{}) != 4 {
panic("TypedCollation should fit in an int32")
}
}
// Coercibility is a numeric value that represents the precedence of a collation
// when applied to a SQL expression. When trying to coerce the collations
// of two different expressions so that they can be compared, the expression
// with the lowest coercibility value will win and its collation will be forced
// upon the other expression.
//
// The rules for assigning a Coercibility value to an expression are as follows:
//
// - An explicit COLLATE clause has a coercibility of 0 (not coercible at all).
// - The concatenation of two strings with different collations has a coercibility of 1.
// - The collation of a column or a stored routine parameter or local variable has a coercibility of 2.
// - A “system constant” (the string returned by functions such as USER() or VERSION()) has a coercibility of 3.
// - The collation of a literal has a coercibility of 4.
// - The collation of a numeric or temporal value has a coercibility of 5.
// - NULL or an expression that is derived from NULL has a coercibility of 6.View on GitHub (pinned to 01a25a7d17)
Solutions
- Revert or rework the struct change so TypedCollation stays 4 bytes (pack fields into existing bit fields).
- If more state is genuinely needed, use a lookup table keyed by the int32 instead of enlarging the struct.
- Update any accompanying codegen/definitions that regenerate the struct, then rebuild.
Example fix
// before
type TypedCollation struct {
Collation uint16
Coercibility Coercibility
Repertoire Repertoire
NewField uint8 // pushes size past 4 bytes
}
// after
type TypedCollation struct {
Collation uint16
Coercibility Coercibility
Repertoire Repertoire // keep total size at 4 bytes
} Defensive patterns
Strategy: validation
Validate before calling
// cannot run before init; instead add a CI test:
func TestTypedCollationSize(t *testing.T) {
require.Equal(t, uintptr(4), unsafe.Sizeof(mysql.TypedCollation{}))
} Prevention
- Never add fields to TypedCollation without recomputing its size; keep it 4 bytes.
- Pack extra state into existing bit fields or an external lookup table.
- Add a CI unit test asserting unsafe.Sizeof(TypedCollation{}) == 4 so it fails before the init panic ever runs.
When it happens
Trigger: Building or running code after someone adds a field to (or changes the packing of) TypedCollation so unsafe.Sizeof(TypedCollation{}) != 4. This fires at process start, before any user code runs.
Common situations: Developers extending TypedCollation with a new field (e.g. adding repertoire flags or a new collation id width); building on an exotic platform/architecture with different alignment rules.
Related errors
- invalid Coercibility value
- listener must take exactly one input argument
- removing from wrong List
- betainc: a or b too big; failed to converge
- Not implemented, post_header_length!=8
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/6cb58a06177b64e6.
Report an issue: GitHub.