{"record":{"id":"29bf0c88bd45f3eb","repo":"owasp-amass/amass","slug":"createassetsbulk-mixed-asset-types-not-allowed","errorCode":null,"errorMessage":"CreateAssetsBulk: mixed asset types not allowed","messagePattern":"CreateAssetsBulk: mixed asset types not allowed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/api/client/v1/client.go","lineNumber":264,"sourceCode":"\t}\n\treturn r.EntityID, nil\n}\n\n// Creates multiple assets in bulk on the server associated with the provided token.\nfunc (c *Client) CreateAssetsBulk(ctx context.Context, token uuid.UUID, atype string, assets []oam.Asset) (int, error) {\n\tatype = strings.ToLower(strings.TrimSpace(atype))\n\n\tif atype == \"\" {\n\t\treturn 0, fmt.Errorf(\"CreateAssetsBulk: asset type required\")\n\t}\n\tif len(assets) > MaxBulkItems {\n\t\treturn 0, fmt.Errorf(\"CreateAssetsBulk: too many items; max=%d\", MaxBulkItems)\n\t}\n\n\titems := make([]json.RawMessage, 0, len(assets))\n\tfor _, asset := range assets {\n\t\tif !strings.EqualFold(atype, string(asset.AssetType())) {\n\t\t\treturn 0, fmt.Errorf(\"CreateAssetsBulk: mixed asset types not allowed\")\n\t\t}\n\n\t\traw, err := asset.JSON()\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\titems = append(items, json.RawMessage(raw))\n\t}\n\n\tsessionID := token.String()\n\tbody, _ := json.Marshal(BulkAddAssetsRequest{Items: items})\n\tu := fmt.Sprintf(\"%s/sessions/%s/assets/%s:bulk\", c.base, sessionID, atype)\n\tresp, err := amasshttp.RequestWebPage(ctx, c.httpClient, &amasshttp.Request{\n\t\tURL:    u,\n\t\tBody:   string(body),\n\t\tMethod: http.MethodPost,\n\t\tHeader: amasshttp.Header{\"Content-Type\": []string{\"application/json\"}},\n\t})","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/owasp-amass/amass/blob/79299dce87b0085db0f2f4ef3e9c52cccb49f514/engine/api/client/v1/client.go#L246-L282","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Partition assets by asset.AssetType() and issue one CreateAssetsBulk call per type.","Filter the slice to only assets whose AssetType() equals atype before calling.","Fix upstream grouping logic so homogeneous batches are produced.","Fall back to per-asset CreateAsset calls for leftover heterogeneous items."],"exampleFix":"// before\nclient.CreateAssetsBulk(ctx, token, \"domain\", mixedAssets) // aborts\n// after\nbyType := map[oam.AssetType][]oam.Asset{}\nfor _, a := range mixedAssets { byType[a.AssetType()] = append(byType[a.AssetType()], a) }\nfor t, list := range byType {\n    if _, err := client.CreateAssetsBulk(ctx, token, string(t), list); err != nil { return err }\n}","handlingStrategy":"validation","validationCode":"for _, a := range assets {\n    if !strings.EqualFold(atype, string(a.AssetType())) { return fmt.Errorf(\"asset %s has type %s, want %s\", a.Key(), a.AssetType(), atype) }\n}","typeGuard":"func homogeneous(atype string, assets []oam.Asset) bool {\n    return !slices.ContainsFunc(assets, func(a oam.Asset) bool { return !strings.EqualFold(atype, string(a.AssetType())) })\n}","tryCatchPattern":"groups := groupByAssetType(assets)\nfor t, list := range groups {\n    if _, err := client.CreateAssetsBulk(ctx, token, string(t), list); err != nil { return err }\n}","preventionTips":["Group assets by AssetType() at the collection layer before flushing.","Never mix asset types in one bulk slice.","Assert slice homogeneity in tests.","Use typed queues per asset type in collection pipelines."],"tags":["validation","api-client","type-mismatch"],"backgroundTag":"invalid-argument-value","analyzedSha":"79299dce87b0085db0f2f4ef3e9c52cccb49f514","analyzedAt":"2026-09-06T08:22:48.198Z","contentChangedAt":"2026-09-06T08:22:48.198Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}