siyuan-note/siyuan · error

relation value is missing

Error message

relation value is missing

What it means

Thrown inside normalizeNewItemTemplateValue (kernel/av/new_item_template.go:419-420) when key.Type == KeyTypeRelation but value.Relation is nil. The function must have a *ValueRelation (containing BlockIDs) to proceed. This check runs before the BlockID validation loop at line 422, so a nil Relation pointer always fails here first.

Source

Thrown at kernel/av/new_item_template.go:420

		var assets []*ValueAsset
		for _, asset := range value.MAsset {
			if nil != asset && "" != strings.TrimSpace(asset.Content) {
				if AssetTypeFile != asset.Type && AssetTypeImage != asset.Type {
					return nil, fmt.Errorf("invalid asset type [%s]", asset.Type)
				}
				assets = append(assets, asset)
			}
		}
		value.MAsset = assets
		value.Text, value.Number, value.Date, value.MSelect, value.URL, value.Email, value.Phone, value.Checkbox, value.Relation = nil, nil, nil, nil, nil, nil, nil, nil, nil
	case KeyTypeCheckbox:
		if nil == value.Checkbox {
			return nil, errors.New("checkbox value is missing")
		}
		value.Text, value.Number, value.Date, value.MSelect, value.URL, value.Email, value.Phone, value.MAsset, value.Relation = nil, nil, nil, nil, nil, nil, nil, nil, nil
	case KeyTypeRelation:
		if nil == value.Relation {
			return nil, errors.New("relation value is missing")
		}
		for _, blockID := range value.Relation.BlockIDs {
			if !ast.IsNodeIDPattern(blockID) {
				return nil, fmt.Errorf("invalid relation block ID [%s]", blockID)
			}
		}
		value.Text, value.Number, value.Date, value.MSelect, value.URL, value.Email, value.Phone, value.MAsset, value.Checkbox = nil, nil, nil, nil, nil, nil, nil, nil, nil
	default:
		return nil, fmt.Errorf("unsupported value type [%s]", key.Type)
	}
	value.Block, value.Template, value.Created, value.Updated, value.Rollup = nil, nil, nil, nil, nil
	value.ID = ""
	value.KeyID = ""
	value.BlockID = ""
	value.Type = key.Type
	value.IsDetached = false
	value.CreatedAt = 0
	value.UpdatedAt = 0

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Include a non-null relation object with a BlockIDs array, e.g. {"relation": {"blockIDs": ["2024010100000000abcd1234"]}}
  2. Omit the field from FieldValues if no default relation is needed
  3. Set Value.Relation = &ValueRelation{BlockIDs: []string{...}} before persisting

Example fix

// before
fieldValue.Value = &av.Value{Type: av.KeyTypeRelation}
// after
fieldValue.Value = &av.Value{Type: av.KeyTypeRelation, Relation: &av.ValueRelation{BlockIDs: []string{"2024010100000000abcd1234"}}}
Defensive patterns

Strategy: validation

Validate before calling

func validateRelationValue(value *av.Value, key *av.Key) error {
    if key.Type == av.KeyTypeRelation && value.Relation == nil {
        return fmt.Errorf("relation key requires a non-nil Value.Relation")
    }
    return nil
}

Type guard

func hasRelationValue(v *av.Value) bool {
    return v != nil && v.Relation != nil
}

Prevention

When it happens

Trigger: Saving an Attribute View new-item template with a static-mode relation field whose Value JSON omits the "relation" sub-field or sets it to null.

Common situations: Programmatic template creation for relation fields that doesn't populate the Relation pointer; frontend serializing a relation value without the blockIDs array; using a template value from a non-relation field type.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/d78d368ea57f35bd. Report an issue: GitHub.