go-gorm/gorm · error

invalid polymorphic foreign keys %+v for %v on field %s

Error message

invalid polymorphic foreign keys %+v for %v on field %s

What it means

In a polymorphic relation with an explicit `foreignKeys` tag (e.g. `gorm:"polymorphic:Owner;foreignKey:CustomKey"`), GORM resolves exactly one primary key field on the owner schema via schema.LookUpField. The error fires when the named key does not exist on the owner schema or when more than one foreign key is listed (polymorphic relations support only one).

Source

Thrown at schema/relationship.go:241

		schema.err = fmt.Errorf("invalid polymorphic type %v for %v on field %s, missing field %s",
			relation.FieldSchema, schema, field.Name, polymorphic+"Type")
	}

	if relation.Polymorphic.PolymorphicID == nil {
		schema.err = fmt.Errorf("invalid polymorphic type %v for %v on field %s, missing field %s",
			relation.FieldSchema, schema, field.Name, polymorphic+"ID")
	}

	if schema.err == nil {
		relation.References = append(relation.References, &Reference{
			PrimaryValue: relation.Polymorphic.Value,
			ForeignKey:   relation.Polymorphic.PolymorphicType,
		})

		primaryKeyField := schema.PrioritizedPrimaryField
		if len(relation.foreignKeys) > 0 {
			if primaryKeyField = schema.LookUpField(relation.foreignKeys[0]); primaryKeyField == nil || len(relation.foreignKeys) > 1 {
				schema.err = fmt.Errorf("invalid polymorphic foreign keys %+v for %v on field %s", relation.foreignKeys,
					schema, field.Name)
			}
		}

		if primaryKeyField == nil {
			schema.err = fmt.Errorf("invalid polymorphic type %v for %v on field %s, missing primaryKey field",
				relation.FieldSchema, schema, field.Name)
			return
		}

		// use same data type for foreign keys
		if copyableDataType(primaryKeyField.DataType) {
			relation.Polymorphic.PolymorphicID.DataType = primaryKeyField.DataType
		}
		relation.Polymorphic.PolymorphicID.GORMDataType = primaryKeyField.GORMDataType
		if relation.Polymorphic.PolymorphicID.Size == 0 {
			relation.Polymorphic.PolymorphicID.Size = primaryKeyField.Size
		}

View on GitHub (pinned to 1d6ce99528)

Solutions

  1. Use a single existing field name in foreignKeys, e.g. `foreignKey:ID`.
  2. Remove the foreignKeys clause entirely to let GORM use PrioritizedPrimaryField.
  3. If a composite key is truly needed, polymorphic relations do not support it — model it as a plain belongs-to with an explicit type column.

Example fix

// before
Children []Cat `gorm:"polymorphic:Owner;foreignKey:Key1,Key2"`

// after
Children []Cat `gorm:"polymorphic:Owner"` // single implicit primary key
Defensive patterns

Strategy: validation

Validate before calling

// Polymorphic foreignKeys must be exactly one existing owner field
type User struct {
    ID uint `gorm:"primaryKey"`
}
// tag must be: polymorphic:Owner;foreignKey:ID  (single, existing)

Try / catch

if err := db.AutoMigrate(&User{}); err != nil {
    if strings.Contains(err.Error(), "invalid polymorphic foreign keys") {
        return fmt.Errorf("use exactly one existing field in foreignKeys for polymorphic relations: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: `gorm:"polymorphic:Owner;foreignKey:NoSuchField"` on a relation, or `foreignKey:A,B` (comma-separated) which makes len(relation.foreignKeys) > 1.

Common situations: Copy-pasting a composite foreign key list from a belongs-to relation into a polymorphic one; renaming the owner's key field without updating the tag; embedding the key in a nested struct not reachable by LookUpField.

Related errors


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