owasp-amass/amass · error

CreateAssetsBulk: mixed asset types not allowed

Error message

CreateAssetsBulk: mixed asset types not allowed

What it means

CreateAssetsBulk requires every asset in the slice to have an AssetType matching the atype parameter (case-insensitive). If any asset differs, the call is rejected client-side to guarantee the bulk endpoint receives a homogeneous batch for the {atype} path segment.

Source

Thrown at engine/api/client/v1/client.go:264

	}
	return r.EntityID, nil
}

// Creates multiple assets in bulk on the server associated with the provided token.
func (c *Client) CreateAssetsBulk(ctx context.Context, token uuid.UUID, atype string, assets []oam.Asset) (int, error) {
	atype = strings.ToLower(strings.TrimSpace(atype))

	if atype == "" {
		return 0, fmt.Errorf("CreateAssetsBulk: asset type required")
	}
	if len(assets) > MaxBulkItems {
		return 0, fmt.Errorf("CreateAssetsBulk: too many items; max=%d", MaxBulkItems)
	}

	items := make([]json.RawMessage, 0, len(assets))
	for _, asset := range assets {
		if !strings.EqualFold(atype, string(asset.AssetType())) {
			return 0, fmt.Errorf("CreateAssetsBulk: mixed asset types not allowed")
		}

		raw, err := asset.JSON()
		if err != nil {
			return 0, err
		}
		items = append(items, json.RawMessage(raw))
	}

	sessionID := token.String()
	body, _ := json.Marshal(BulkAddAssetsRequest{Items: items})
	u := fmt.Sprintf("%s/sessions/%s/assets/%s:bulk", c.base, sessionID, atype)
	resp, err := amasshttp.RequestWebPage(ctx, c.httpClient, &amasshttp.Request{
		URL:    u,
		Body:   string(body),
		Method: http.MethodPost,
		Header: amasshttp.Header{"Content-Type": []string{"application/json"}},
	})

View on GitHub (pinned to 79299dce87)

Solutions

  1. Partition assets by asset.AssetType() and issue one CreateAssetsBulk call per type.
  2. Filter the slice to only assets whose AssetType() equals atype before calling.
  3. Fix upstream grouping logic so homogeneous batches are produced.
  4. Fall back to per-asset CreateAsset calls for leftover heterogeneous items.

Example fix

// before
client.CreateAssetsBulk(ctx, token, "domain", mixedAssets) // aborts
// after
byType := map[oam.AssetType][]oam.Asset{}
for _, a := range mixedAssets { byType[a.AssetType()] = append(byType[a.AssetType()], a) }
for t, list := range byType {
    if _, err := client.CreateAssetsBulk(ctx, token, string(t), list); err != nil { return err }
}
Defensive patterns

Strategy: validation

Validate before calling

for _, a := range assets {
    if !strings.EqualFold(atype, string(a.AssetType())) { return fmt.Errorf("asset %s has type %s, want %s", a.Key(), a.AssetType(), atype) }
}

Type guard

func homogeneous(atype string, assets []oam.Asset) bool {
    return !slices.ContainsFunc(assets, func(a oam.Asset) bool { return !strings.EqualFold(atype, string(a.AssetType())) })
}

Try / catch

groups := groupByAssetType(assets)
for t, list := range groups {
    if _, err := client.CreateAssetsBulk(ctx, token, string(t), list); err != nil { return err }
}

Prevention

When it happens

Trigger: Calling Client.CreateAssetsBulk(ctx, token, "domain", assets) where assets contains e.g. oam.IPAddress or oam.Netblock assets mixed in — any single mismatch aborts the whole batch.

Common situations: Collecting assets of multiple types into one slice from an enumeration pipeline and flushing them in a single bulk call; forgetting to partition by AssetType before flushing.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of owasp-amass/amass@79299dce87 (2026-09-06). Data as JSON: /api/errors/29bf0c88bd45f3eb. Report an issue: GitHub.