owasp-amass/amass · error

addAssetsBulk: status=%s error=%s

Error message

addAssetsBulk: status=%s error=%s

What it means

CreateAssetsBulk's informative failure variant: the server returned non-200 with a parseable JSON error body, so the client surfaces the status plus the server's error message. The bulk insert failed as a whole per server semantics.

Source

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

	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"}},
	})
	if err != nil {
		return 0, err
	}

	if resp.StatusCode != http.StatusOK {
		msg, err := readJSONError(resp.Body)
		if err != nil {
			return 0, fmt.Errorf("addAssetsBulk: status=%s", resp.Status)
		}
		return 0, fmt.Errorf("addAssetsBulk: status=%s error=%s", resp.Status, msg)
	}

	var out BulkAddAssetsResponse
	if err := json.Unmarshal([]byte(resp.Body), &out); err != nil {
		return 0, err
	}
	return int(out.Stored), nil
}

// Subscribe to receive a stream of log messages from the server.
func (c *Client) Subscribe(ctx context.Context, token uuid.UUID) (<-chan string, error) {
	u, err := url.Parse(c.base)
	if err != nil {
		return nil, err
	}

	switch u.Scheme {
	case "http":

View on GitHub (pinned to 79299dce87)

Solutions

  1. Read the error=%s portion for the server's specific rejection reason.
  2. Fix the offending asset data per the server message.
  3. Re-authenticate and refresh the session token if the status was 401.
  4. Confirm the deployed server supports the :bulk endpoint; otherwise use per-asset CreateAsset.
  5. Retry transient 5xx failures.

Example fix

// before
_, err := client.CreateAssetsBulk(ctx, token, atype, assets)
// after
_, err := client.CreateAssetsBulk(ctx, token, atype, assets)
if err != nil {
    if strings.Contains(err.Error(), "status=401") { token = reauth(ctx); return retry() }
    return err
}
Defensive patterns

Strategy: try-catch

Validate before calling

if token == uuid.Nil { return errors.New("session token not initialized") }
for _, a := range assets { if _, err := a.JSON(); err != nil { return err } }

Type guard

func isAuthFailure(err error) bool { return err != nil && strings.Contains(err.Error(), "status=401") }

Try / catch

count, err := client.CreateAssetsBulk(ctx, token, atype, assets)
if err != nil {
    if isAuthFailure(err) { token = reauth(ctx); return client.CreateAssetsBulk(ctx, token, atype, assets) }
    return fmt.Errorf("bulk add rejected: %w", err)
}

Prevention

When it happens

Trigger: Calling CreateAssetsBulk when the server explicitly rejects the batch — invalid token (401), unsupported asset type on :bulk path (404), validation or storage failure (400/500) — with a JSON error envelope.

Common situations: Server-side schema validation rejecting one asset shape, hitting an older server without the bulk endpoint, or expired session tokens in long-running workers.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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