projectdiscovery/nuclei · error

could not upload results got status code %v on %v

Error message

could not upload results got status code %v on %v

What it means

The periodic results upload POST returned a non-200 status (internal/pdcp/writer.go:228); the error includes both the status code and the exact request URL, which distinguishes auth problems (401/403), wrong endpoints (404), rate limiting (429) and server faults (5xx). Transport-level failures surface separately as errkit-wrapped 'could not upload results', so this error specifically means the server answered with an unexpected status. The response body is read first, and a successful ID is recorded only on 200.

Source

Thrown at internal/pdcp/writer.go:228

func (u *UploadWriter) upload(data []byte) error {
	req, err := u.getRequest(data)
	if err != nil {
		return errkit.Wrap(err, "could not create upload request")
	}
	resp, err := u.client.Do(req)
	if err != nil {
		return errkit.Wrap(err, "could not upload results")
	}
	defer func() {
		_ = resp.Body.Close()
	}()
	bin, err := io.ReadAll(resp.Body)
	if err != nil {
		return errkit.Wrap(err, "could not get id from response")
	}
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("could not upload results got status code %v on %v", resp.StatusCode, resp.Request.URL.String())
	}
	var uploadResp uploadResponse
	if err := json.Unmarshal(bin, &uploadResp); err != nil {
		return errkit.Wrap(err, fmt.Sprintf("could not unmarshal response got %v", string(bin)))
	}
	if uploadResp.ID != "" && u.scanID == "" {
		u.scanID = uploadResp.ID
	}
	return nil
}

// getRequest returns a new request for upload
// if scanID is not provided create new scan by uploading the data
// if scanID is provided append the data to existing scan
func (u *UploadWriter) getRequest(bin []byte) (*retryablehttp.Request, error) {
	var method, url string

	if u.scanID == "" {

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. On 401/403 re-authenticate (nuclei auth) and verify team membership/permissions
  2. Confirm the configured API server URL points at the intended PDCP endpoint
  3. Treat 429/5xx as transient — uploads are periodic and usually self-heal on later ticks
  4. Check the ProjectDiscovery cloud status for incidents
Defensive patterns

Strategy: retry

Try / catch

err := uploadTick(ctx)
if err != nil {
    msg := err.Error()
    if strings.Contains(msg, "status code 401") || strings.Contains(msg, "status code 403") {
        return fmt.Errorf("pdcp token rejected: re-authenticate") // fail fast
    }
    if strings.Contains(msg, "status code 429") || strings.Contains(msg, "status code 5") {
        backoff.RetryNotify(uploadTick, backoff.NewExponentialBackOff(), notify) // transient
    }
    return err
}

Prevention

When it happens

Trigger: Expired or invalid PDCP token (401); token lacking access to the team/scan (403); misconfigured custom API base URL (404); upstream incidents or rate limits (429/5xx) during long scans.

Common situations: Long-running scans whose token expires mid-run; rotated or revoked API keys; wrong -server URL; upstream service degradation.

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/6e61c609454f3cba. Report an issue: GitHub.