{"record":{"id":"cbaed6d8923f9932","repo":"hashicorp/nomad","slug":"unknown-port-label-q","errorCode":null,"errorMessage":"Unknown port label %q","messagePattern":"Unknown port label %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/qemu/driver.go","lineNumber":603,"sourceCode":"\t// For example, args = [ \"-nodefconfig\", \"-nodefaults\" ]\n\t// This will allow a VM with embedded configuration to boot successfully.\n\targs = append(args, driverConfig.Args...)\n\n\t// Check the Resources required Networks to add port mappings. If no resources\n\t// are required, we assume the VM is a purely compute job and does not require\n\t// the outside world to be able to reach it. VMs ran without port mappings can\n\t// still reach out to the world, but without port mappings it is effectively\n\t// firewalled\n\tprotocols := []string{\"udp\", \"tcp\"}\n\tif len(cfg.Resources.NomadResources.Networks) > 0 {\n\t\t// Loop through the port map and construct the hostfwd string, to map\n\t\t// reserved ports to the ports listenting in the VM\n\t\t// Ex: hostfwd=tcp::22000-:22,hostfwd=tcp::80-:8080\n\t\ttaskPorts := cfg.Resources.NomadResources.Networks[0].PortLabels()\n\t\tfor label, guest := range driverConfig.PortMap {\n\t\t\thost, ok := taskPorts[label]\n\t\t\tif !ok {\n\t\t\t\treturn nil, nil, fmt.Errorf(\"Unknown port label %q\", label)\n\t\t\t}\n\n\t\t\tfor _, p := range protocols {\n\t\t\t\tnetdevArgs = append(netdevArgs, fmt.Sprintf(\"hostfwd=%s::%d-:%d\", p, host, guest))\n\t\t\t}\n\t\t}\n\n\t\tif len(netdevArgs) != 0 {\n\t\t\targs = append(args,\n\t\t\t\t\"-netdev\",\n\t\t\t\tfmt.Sprintf(\"user,id=user.0,%s\", strings.Join(netdevArgs, \",\")),\n\t\t\t\t\"-device\", \"virtio-net,netdev=user.0\",\n\t\t\t)\n\t\t}\n\t}\n\n\t// If using KVM, add optimization args\n\tif accelerator == \"kvm\" {","sourceCodeStart":585,"sourceCodeEnd":621,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/qemu/driver.go#L585-L621","documentation":"When a port_map is given, StartTask maps each entry (label -> guest port) to a host port taken from the first declared network resource. If the task's network block declares no port with the given label, PortLabels() lookup fails and StartTask returns this error instead of building the hostfwd args. Every port_map key must correspond to a static or dynamic port label in the task's network resources.","triggerScenarios":"driver config port_map contains a label (e.g. \"http\") that is not declared as a port in the task's network stanza; network stanza omitted entirely (so NomadResources.Networks is empty/mislabeled); label typo between port_map and the network block.","commonSituations":"Task author renames a port label in the network block but forgets port_map; port_map written for a driver that does not require a network block; copy-pasted port_map from another task with different labels; multiple network blocks where only Networks[0] is consulted so labels live in a later block.","solutions":["Declare a matching port in the task's network block for every port_map key: network { port \"http\" {} } plus port_map { http = 80 }.","Make label strings in port_map and the network stanza match exactly (case-sensitive).","If multiple network blocks exist, ensure the needed labels are in the first one."],"exampleFix":"// before\nnetwork {\n  port \"web\" {}\n}\n// port_map uses \"http\" -> Unknown port label\n// after\nnetwork {\n  port \"http\" {}\n}\n// port_map { http = 80 }","handlingStrategy":"validation","validationCode":"function validatePortMap(task) {\n  const netLabels = new Set(\n    (task.resources?.networks || []).flatMap((n) => Object.keys(n.port_labels || n[\"port\"] || {}))\n  );\n  for (const label of Object.keys(task.driver?.port_map || {})) {\n    if (!netLabels.has(label)) {\n      throw new Error(`Unknown port label ${label}: declare it in the network block`);\n    }\n  }\n}","typeGuard":"function portMapLabelsDeclared(task) {\n  const labels = new Set((task.resources?.networks?.[0]?.ports || []).map((p) => p.label));\n  return Object.keys(task.driver?.port_map || {}).every((l) => labels.has(l));\n}","tryCatchPattern":"try {\n  await nomad.jobs.register(job);\n} catch (e) {\n  if (String(e.message).startsWith(\"Unknown port label\")) {\n    const label = JSON.parse(JSON.stringify(e.message)).match(/\"(.*)\"/)?.[1];\n    console.error(`Add network port \"${label}\" to the task's network block`);\n  }\n  throw e;\n}","preventionTips":["Keep port_map keys and network port labels in one template source so they cannot drift.","Declare ports in the first network block — only Networks[0] is consulted.","Label matching is case-sensitive; use consistent casing.","Dry-run job parsing (nomad job validate) before submitting."],"tags":["qemu","networking","port-mapping","nomad"],"backgroundTag":"unknown-port-label","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}