netbirdio/netbird · error

upload failed: %s

Error message

upload failed: %s

What it means

After the daemon assembled the debug bundle, it attempted the upload and reported a failure reason string in the response, which the CLI surfaces here. The bundle file itself was still created locally (its path is printed just above this error). The reason text comes from the daemon's upload attempt: unreachable or invalid upload URL, TLS verification failure against the target, an HTTP error status from the receiving endpoint, or a blocked egress path.

Source

Thrown at client/cmd/debug.go:193

	request := &proto.DebugBundleRequest{
		Anonymize:      anonymizeEnabled,
		AnonymizeLevel: anonymizeLevel.String(),
		SystemInfo:     systemInfoFlag,
		LogFileCount:   logFileCount,
		CliVersion:     version.NetbirdVersion(),
	}
	if uploadBundleFlag {
		request.UploadURL = uploadBundleURLFlag
		request.UploadInsecure = uploadBundleInsecureFlag
	}
	resp, err := client.DebugBundle(cmd.Context(), request)
	if err != nil {
		return daemonCallError("bundle debug", err)
	}
	cmd.Printf("Local file:\n%s\n", resp.GetPath())

	if resp.GetUploadFailureReason() != "" {
		return fmt.Errorf("upload failed: %s", resp.GetUploadFailureReason())
	}

	if uploadBundleFlag {
		cmd.Printf("Upload file key:\n%s\n", resp.GetUploadedKey())
	}

	return nil
}

func setLogLevel(cmd *cobra.Command, args []string) error {
	conn, err := getClient(cmd)
	if err != nil {
		return err
	}
	defer func() {
		if err := conn.Close(); err != nil {
			log.Errorf(errCloseConnection, err)
		}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Read the printed reason: DNS/connectivity messages mean fix reachability; TLS messages mean fix the certificate or pass --upload-insecure (only for trusted internal endpoints); HTTP status text means inspect the server side
  2. Verify the URL with curl -v --data-binary @<bundle-path> <url> from the same machine to reproduce independently
  3. For proxy body-size limits, raise the limit on the receiving server or reduce bundle size (fewer log files via --log-file-count, disable system info)
  4. The local file path printed before the error still holds the full bundle — share it manually if upload cannot be fixed

Example fix

# before: private-CA upload endpoint, secure verify fails
netbird debug bundle --upload --url https://collector.internal/debug
# -> upload failed: tls: failed to verify certificate

# after: trust the internal endpoint explicitly
netbird debug bundle --upload --url https://collector.internal/debug --upload-insecure
Defensive patterns

Strategy: validation

Validate before calling

// Probe the upload endpoint before asking the daemon to upload:
u, err := url.Parse(uploadURL)
if err != nil || (u.Scheme != "https" && u.Scheme != "http") {
    return fmt.Errorf("invalid upload URL")
}
if _, err := http.Head(uploadURL); err != nil && !isHTTPOK(err) {
    // connectivity/TLS problem: fix before running with --upload
}

Type guard

// Distinguish the three failure families from the reason string:
func classifyUploadFailure(reason string) string {
    switch {
    case strings.Contains(reason, "tls:"):
        return "certificate"
    case strings.Contains(reason, "connection refused"), strings.Contains(reason, "no such host"):
        return "connectivity"
    default:
        return "server"
    }
}

Try / catch

// Always keep the local bundle even when upload fails:
if err := runBundle(); err != nil {
    if strings.HasPrefix(err.Error(), "upload failed") {
        warn(err) // local path was already printed; upload can be retried manually
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: --upload with a URL that is wrong (typo, wrong scheme, missing endpoint path); the receiving endpoint returns 4xx/5xx (auth required, size limits); self-signed or internal-CA certificate on the upload server without --upload-insecure; device egress blocking the upload host (firewall/proxy); DNS failure for the upload host.

Common situations: Support-tool flows where the URL was transcribed manually; uploads to an internal collector with a private CA while the flag for insecure upload was not passed; large bundles exceeding a reverse-proxy body limit (nginx client_max_body_size); cloud environments with egress allow-lists.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/0d5681e5d4e43f31. Report an issue: GitHub.