{"record":{"id":"1197839c8b5f27d2","repo":"amir20/dozzle","slug":"invalid-host-id-s","errorCode":null,"errorMessage":"invalid host id: %s","messagePattern":"invalid host id: (.+?)","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/web/download.go","lineNumber":95,"sourceCode":"\t\tfor _, level := range r.URL.Query()[\"levels\"] {\n\t\t\tlevels[level] = struct{}{}\n\t\t}\n\t}\n\n\t// Validate all containers before starting to write response\n\ttype containerInfo struct {\n\t\thostId           string\n\t\thost             string\n\t\tid               string\n\t\tcontainerService *container_support.ContainerService\n\t}\n\tcontainers := make([]containerInfo, 0, len(hostIds))\n\n\tfor _, hostId := range hostIds {\n\t\tparts := strings.Split(hostId, \"~\")\n\t\tif len(parts) != 2 {\n\t\t\tlog.Error().Msgf(\"invalid host id: %s\", hostId)\n\t\t\thttp.Error(w, fmt.Sprintf(\"invalid host id: %s\", hostId), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\n\t\thost := parts[0]\n\t\tid := parts[1]\n\t\tcontainerService, err := h.hostService.FindContainer(host, id, userLabels)\n\t\tif err != nil {\n\t\t\tlog.Error().Err(err).Msgf(\"error finding container %s\", id)\n\t\t\thttp.Error(w, fmt.Sprintf(\"error finding container %s: %v\", id, err), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\n\t\tcontainers = append(containers, containerInfo{\n\t\t\thostId:           hostId,\n\t\t\thost:             host,\n\t\t\tid:               id,\n\t\t\tcontainerService: containerService,\n\t\t})","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/amir20/dozzle/blob/d9463cbe21874e44ab79db6fa63e746ca7d22928/internal/web/download.go#L77-L113","documentation":"downloadLogs expects each entry of the `id` path/query value to be a composite \"host~containerId\" token; it splits on \"~\" and requires exactly 2 parts. A 400 \"invalid host id: %s\" is returned when the separator is missing or there is more than one \"~\".","triggerScenarios":"GET download endpoint with ids like \"abc123\" (no host prefix), \"host~a~b\", or an empty id, producing len(strings.Split(id, \"~\")) != 2.","commonSituations":"Old bookmarks/links predating the host~id scheme; callers passing a bare Docker container ID; frontend state that lost the host component; IDs echoed through other tools that split or re-join on different separators.","solutions":["Build the identifier as `${hostId}~${containerId}` before calling the endpoint.","Trim and re-check stored IDs/URLs for stale or malformed host~id values.","Use the container object from the API (which already carries host and id fields) instead of hand-assembling strings."],"exampleFix":"// before\nfetch(`/api/hosts/${container.id}/download`)\n// after\nfetch(`/api/hosts/${container.host}~${container.id}/download`)","handlingStrategy":"validation","validationCode":"function isCompositeId(id) {\n  const parts = String(id).split('~');\n  return parts.length === 2 && parts[0].length > 0 && parts[1].length > 0;\n}\nif (!isCompositeId(id)) throw new Error(`invalid host id: ${id}`)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always derive identifiers from the container API object (host + id fields), never from stored strings.","Validate host~id format before building URLs.","Beware separators: container ids never contain ~, but verify anyway."],"tags":["http","validation","identifier"],"backgroundTag":"invalid-identifier-format","analyzedSha":"d9463cbe21874e44ab79db6fa63e746ca7d22928","analyzedAt":"2026-09-07T10:08:55.855Z","contentChangedAt":"2026-09-07T10:08:55.855Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}