weaviate/weaviate · error

target is a single-target reference, need multi-target %v

Error message

target is a single-target reference, need multi-target %v

What it means

extractMultiRefTarget handles pb reference properties of the multi-target kind. If the property's schema declares fewer than two data types — i.e. it is a plain single-target reference — the multi-target path is invalid and this error is returned listing the property's single data type. The target collection is qualified via namespacing rules before being used for the beacon.

Source

Thrown at adapters/handlers/grpc/v1/batch/parse.go:170

		toClass := namespacing.StripQualification(prop.DataType[0])
		beacons := make([]interface{}, len(refSingle.Uuids))
		for j, uuid := range refSingle.Uuids {
			beacons[j] = map[string]interface{}{"beacon": BEACON_START + toClass + "/" + uuid}
		}
		props[propName] = beacons
	}
	return nil
}

func extractMultiRefTarget(class *models.Class, properties []*pb.BatchObject_MultiTargetRefProps, props map[string]interface{}, principal *models.Principal, namespacesEnabled bool) error {
	for _, refMulti := range properties {
		propName := refMulti.GetPropName()
		prop, err := schema.GetPropertyByName(class, propName)
		if err != nil {
			return err
		}
		if len(prop.DataType) < 2 {
			return fmt.Errorf("target is a single-target reference, need multi-target %v", prop.DataType)
		}
		// TargetCollection is user-supplied; route through QualifyRefTarget
		// for cross-NS policy + storage-shape rule.
		targetCollection := schema.UppercaseClassName(refMulti.TargetCollection)
		_, shortTarget, err := namespacing.QualifyRefTarget(principal, namespacesEnabled, class.Class, targetCollection)
		if err != nil {
			return err
		}
		beacons := make([]interface{}, len(refMulti.Uuids))
		for j, uid := range refMulti.Uuids {
			beacons[j] = map[string]interface{}{"beacon": BEACON_START + shortTarget + "/" + uid}
		}
		if props[propName] == nil {
			props[propName] = beacons
		} else {
			props[propName] = append(props[propName].([]interface{}), beacons...)
		}
	}

View on GitHub (pinned to 75aa4b6d11)

Solutions

  1. Send the reference via refs_single instead of refs_multi
  2. Inspect the schema: if the property should be multi-target, recreate it with an array of target classes
  3. Remove target_collection from the request and align with the single-target property
  4. Align the client SDK with the current schema definition

Example fix

// before: property 'hasAuthor' is single-target ["Author"]
refs_multi: [{prop_name: "hasAuthor", target_collection: "Author", uuids: ["..."]}]
// after
refs_single: [{prop_name: "hasAuthor", uuids: ["..."]}]
Defensive patterns

Strategy: validation

Validate before calling

const prop = schema.classes.find(c => c.class === 'Post').properties.find(p => p.name === 'hasAuthor');
if (Array.isArray(prop.dataTypes) && prop.dataTypes.length === 1) {
  // must use single-target reference shape (refs_single)
}

Type guard

function isSingleTargetProperty(prop) {
  return Array.isArray(prop?.dataTypes) && prop.dataTypes.length === 1;
}

Try / catch

resp, err := client.BatchObjects(ctx, req)
if err != nil && strings.Contains(err.Error(), "single-target reference") {
  return fmt.Errorf("rebuild request using the single-target (refs_single) reference shape: %w", err)
}

Prevention

When it happens

Trigger: Sending a pb.BatchObject with refs_multi (target_collection set) for a property declared as a single-target reference (one dataType).

Common situations: Client SDK version older than multi-target support sending everything as multi-target; payload reuse across collections; property redefined as single-target after being multi-target while clients still send the multi-target shape.

Related errors


AI-assisted analysis of weaviate/weaviate@75aa4b6d11 (2026-09-04). Data as JSON: /api/errors/be7cb45bc26bf0cc. Report an issue: GitHub.