{"record":{"id":"df1bf37aef9e22e0","repo":"derailed/k9s","slug":"invalid-port-forward-specification-s","errorCode":null,"errorMessage":"invalid port-forward specification %s","messagePattern":"invalid port-forward specification (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/port/pf.go","lineNumber":67,"sourceCode":"\t\treturn &pf, nil\n\t}\n\tpf.LocalPort, pf.ContainerPort = mm[1], intstr.Parse(mm[2])\n\n\treturn &pf, nil\n}\n\n// ParsePF hydrate a portforward annotation from string.\nfunc ParsePF(ann string) (*PFAnn, error) {\n\tif pf, err := ParsePlainPF(ann); err == nil {\n\t\treturn pf, nil\n\t}\n\tvar pf PFAnn\n\tif mm := pfPlainRX.FindStringSubmatch(strings.TrimSpace(ann)); len(mm) == 3 {\n\t\tpf.containerPortNum = mm[0]\n\t}\n\tr := pfRX.FindStringSubmatch(strings.TrimSpace(ann))\n\tif len(r) < 4 {\n\t\treturn &pf, fmt.Errorf(\"invalid port-forward specification %s\", ann)\n\t}\n\tpf.Container = r[1]\n\tpf.LocalPort, pf.ContainerPort = r[2], intstr.Parse(r[3])\n\tif r[3] == \"\" {\n\t\tpf.ContainerPort = intstr.Parse(pf.LocalPort)\n\t}\n\n\t// Testing only!\n\tif len(r) == 5 && r[4] != \"\" {\n\t\tpf.containerPortNum = r[4]\n\t}\n\tif pf.LocalPort == \"\" {\n\t\tpf.LocalPort = pf.containerPortNum\n\t}\n\n\treturn &pf, nil\n}\n","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/port/pf.go#L49-L85","documentation":"Thrown by port.ParsePF when the annotation matches neither the plain form nor the full form regex \\A([\\w-]+)::(\\d*):(\\d*|[\\w-]*)/?(\\d+)?\\z, i.e. 'container::localPort:containerPort[/portNum]'. It is the generic 'not a port-forward spec k9s understands' error.","triggerScenarios":"Values like 'svc:8080:9090' (single colon before container segment), '::8080:80' (empty container, [\\w-]+ requires at least one character), 'ns/svc::8080' (slash in container name), or '8080:80:90' (three colon-separated fields with no '::').","commonSituations":"Typos between ':' and '::' in hand-written annotations; copying 'namespace/service:port' kubectl syntax; k9s version changes that tightened the accepted grammar; annotation placed under the wrong key so unrelated text is parsed.","solutions":["Use the full form 'container::localPort:containerPort', e.g. 'mysvc::8080:9090'","Keep the container segment to letters, digits, underscore and hyphen only (no '/', '.', ':')","Keep the local port numeric; named ports are only valid for the container port","Print the raw annotation (kubectl get <res> -o jsonpath='{.metadata.annotations.k9scli\\.io/port-forwards}') and eyeball it against the two accepted forms"],"exampleFix":"# before\nk9scli.io/port-forwards: \"mysvc:8080:9090\"\n# after\nk9scli.io/port-forwards: \"mysvc::8080:9090\"","handlingStrategy":"validation","validationCode":"var (\n\tplainPFRX = regexp.MustCompile(`\\A(\\d*):(\\d*|[\\w-]*)\\z`)\n\tfullPFRX  = regexp.MustCompile(`\\A([\\w-]+)::(\\d*):(\\d*|[\\w-]*)/?(\\d+)?\\z`)\n)\n\nfunc validPF(ann string) bool {\n\ts := strings.TrimSpace(ann)\n\treturn plainPFRX.MatchString(s) || fullPFRX.MatchString(s)\n}","typeGuard":null,"tryCatchPattern":"On error from port.ParsePF, wrap with context (fmt.Errorf(\"parsing port-forward annotation %q: %w\", ann, err)) and surface to the user as a config hint; do not retry — the string is deterministic.","preventionTips":["Generate annotations from templates that interpolate validated container/port variables","Document '::' vs ':' distinction wherever port-forwards are configured","Unit-test both accepted forms plus common malformed forms in your tooling"],"tags":["port-forward","annotation","parsing","kubernetes"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}