amir20/dozzle · error

no container ids provided

Error message

no container ids provided

What it means

downloadLogs splits the `hostIds` URL path parameter on commas and errors with 400 if none were provided. Note a practical quirk: strings.Split never returns an empty slice, so this fires when the URL captures an empty hostIds segment, meaning the route was hit with a blank id list.

Solutions

  1. Fix the URL to include at least one host/container id: /api/hosts/{hostId}/logs/download.
  2. Check the frontend code that constructs the download link and ensure the id is non-empty before navigation.
  3. Verify the container or host you are downloading from actually exists and its id is populated.

Example fix

// before
/api/hosts//logs/download
// after
/api/hosts/local/logs/download?stdout=true
Defensive patterns

Strategy: validation

Validate before calling

const ids = [hostId].filter(Boolean);
if (ids.length === 0) return; // do not build a download URL without an id
const url = `/api/hosts/${ids.join(',')}/logs/download?stdout=true`;

Type guard

function canDownload(hostId: string | undefined): hostId is string {
  return typeof hostId === 'string' && hostId.length > 0;
}

Prevention

When it happens

Trigger: Requesting the download endpoint with an empty {hostIds} path segment, e.g. GET /api/hosts//logs/download or a hand-crafted/malformed URL where the param resolves to an empty string.

Common situations: Frontend bug building the download URL from an empty container/host id; user hits the endpoint manually; URL templating left the placeholder unexpanded.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07). Data as JSON: /api/errors/4924bfe322afba98. Report an issue: GitHub.

Appendix: source

Thrown at internal/web/download.go:24

	"io"
	"net/http"
	"regexp"
	"strings"
	"time"

	"github.com/amir20/dozzle/internal/auth"
	"github.com/amir20/dozzle/internal/container"
	container_support "github.com/amir20/dozzle/internal/support/container"
	support_web "github.com/amir20/dozzle/internal/support/web"
	"github.com/go-chi/chi/v5"
	"github.com/rs/zerolog/log"
)

func (h *handler) downloadLogs(w http.ResponseWriter, r *http.Request) {
	hostIds := strings.Split(chi.URLParam(r, "hostIds"), ",")
	if len(hostIds) == 0 {
		log.Error().Msg("no container ids provided")
		http.Error(w, "no container ids provided", http.StatusBadRequest)
		return
	}

	userLabels := h.config.Labels
	permit := true
	if h.config.Authorization.Provider != NONE {
		user := auth.UserFromContext(r.Context())
		if user.ContainerLabels.Exists() {
			userLabels = user.ContainerLabels
		}
		permit = user.Roles.Has(auth.Download)
	}

	if !permit {
		log.Warn().Msg("user is not permitted to download logs from container")
		http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
		return
	}

View on GitHub (pinned to d9463cbe21)