go-gorm/gorm · error

unsupported relations: %s

Error message

unsupported relations: %s

What it means

db.Association(column) parses the model and looks up db.Statement.Schema.Relationships.Relations[column]. When the named column is not a relation (typo, plain field, or missing embedded relation), it wraps ErrUnsupportedRelation: fmt.Errorf("%w: %s", ErrUnsupportedRelation, column). The Association object carries this error in association.Error.

Source

Thrown at association.go:30

// Association Mode contains some helper methods to handle relationship things easily.
type Association struct {
	DB           *DB
	Relationship *schema.Relationship
	Unscope      bool
	Error        error
}

func (db *DB) Association(column string) *Association {
	association := &Association{DB: db, Unscope: db.Statement.Unscoped}
	table := db.Statement.Table

	if association.Error = db.Statement.Parse(db.Statement.Model); association.Error == nil {
		db.Statement.Table = table
		association.Relationship = db.Statement.Schema.Relationships.Relations[column]

		if association.Relationship == nil {
			association.Error = fmt.Errorf("%w: %s", ErrUnsupportedRelation, column)
		}

		db.Statement.ReflectValue = reflect.ValueOf(db.Statement.Model)
		for db.Statement.ReflectValue.Kind() == reflect.Ptr {
			db.Statement.ReflectValue = db.Statement.ReflectValue.Elem()
		}
	}

	return association
}

func (association *Association) Unscoped() *Association {
	return &Association{
		DB:           association.DB,
		Relationship: association.Relationship,
		Error:        association.Error,
		Unscope:      true,
	}

View on GitHub (pinned to 1d6ce99528)

Solutions

  1. Use the exact Go field name of the relation: Association("Orders"), not the column or table name.
  2. Check assoc.Error immediately after obtaining the Association handle before calling Append/Replace/etc.
  3. If the field is genuinely a relation but not recognized, verify it is not ignored (`gorm:"-"`) and its type is a struct/slice of struct/pointer.
  4. Centralize association-name strings as constants next to the model.

Example fix

// before
assoc := db.Model(&user).Association("orders") // typo -> ErrUnsupportedRelation: orders

// after
const AssocOrders = "Orders"
assoc := db.Model(&user).Association(AssocOrders)
if assoc.Error != nil { return assoc.Error }
Defensive patterns

Strategy: validation

Validate before calling

func relationExists(db *gorm.DB, model interface{}, name string) bool {
    stmt := &gorm.Statement{DB: db}
    if err := stmt.Parse(model); err != nil { return false }
    _, ok := stmt.Schema.Relationships.Relations[name]
    return ok
}
// before:
if !relationExists(db, &User{}, "Orders") { return errors.New("bad association") }

Try / catch

assoc := db.Model(&user).Association("Orders")
if assoc.Error != nil {
    if errors.Is(assoc.Error, gorm.ErrUnsupportedRelation) { /* wrong name */ }
    return assoc.Error
}

Prevention

When it happens

Trigger: Calling db.Model(&user).Association("Ordr") (typo), Association("Name") where Name is a string column not a relation, or Association on a model whose relation field is tagged `gorm:"-"` so it is excluded from Relationships.

Common situations: Renaming a relation field but not updating the string in service code (no compile-time check on these strings); using a column name instead of the Go field name; embedding structs so the relation lives at a different name; copy-paste between models.

Related errors


AI-assisted analysis of go-gorm/gorm@1d6ce99528 (2026-08-15). Data as JSON: /api/errors/bf60404f338d48dd. Report an issue: GitHub.