{"record":{"id":"5a295b13bf555236","repo":"tailscale/tailscale","slug":"failed-to-parse-latest-version-from-apk-info-tail","errorCode":null,"errorMessage":"failed to parse latest version from \"apk info tailscale\": %w","messagePattern":"failed to parse latest version from \"apk info tailscale\": %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"clientupdate/clientupdate.go","lineNumber":722,"sourceCode":"\t}\n\n\tdefer func() {\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(`%w; you can try updating using \"apk upgrade tailscale\"`, err)\n\t\t}\n\t}()\n\n\tout, err := exec.Command(\"apk\", \"update\").CombinedOutput()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed refresh apk repository indexes: %w, output:\\n%s\", err, out)\n\t}\n\tout, err = exec.Command(\"apk\", \"info\", \"tailscale\").CombinedOutput()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed checking apk for latest tailscale version: %w, output:\\n%s\", err, out)\n\t}\n\tver, err := parseAlpinePackageVersion(out)\n\tif err != nil {\n\t\treturn fmt.Errorf(`failed to parse latest version from \"apk info tailscale\": %w`, err)\n\t}\n\tif !up.confirm(ver) {\n\t\tif err := checkOutdatedAlpineRepo(up.Logf, apkDirPaths, ver, up.Track); err != nil {\n\t\t\tup.Logf(\"failed to check whether Alpine release is outdated: %v\", err)\n\t\t}\n\t\treturn nil\n\t}\n\n\tcmd := exec.Command(\"apk\", \"upgrade\", \"tailscale\")\n\tcmd.Stdout = up.Stdout\n\tcmd.Stderr = up.Stderr\n\tif err := cmd.Run(); err != nil {\n\t\treturn fmt.Errorf(\"failed tailscale update using apk: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc parseAlpinePackageVersion(out []byte) (string, error) {","sourceCodeStart":704,"sourceCodeEnd":740,"githubUrl":"https://github.com/tailscale/tailscale/blob/cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042/clientupdate/clientupdate.go#L704-L740","documentation":"updateAlpineLike passes 'apk info tailscale' output to parseAlpinePackageVersion; if the parser fails, the error is re-wrapped as 'failed to parse latest version from \"apk info tailscale\"' so the caller knows the discovery step, not the upgrade, broke. The underlying error is either a malformed info line or 'tailscale version not found in output' from the same parser.","triggerScenarios":"'apk info tailscale' exits zero but its output contains either a 'tailscale-'-prefixed line that does not split into at least 3 dash-separated fields (malformed info line error) or no 'tailscale-'-prefixed line at all (errors.New(\"tailscale version not found in output\") in the same function).","commonSituations":"A newer apk-tools changes the info output format or wraps description lines; localized output prefixes breaking the expected 'tailscale-<ver>-<rel> description:' shape; tailscale present only as a virtual/dependency name so no version line is printed.","solutions":["Run 'apk info tailscale' and inspect the exact line format that starts with tailscale-","Rule out localized output: run 'LC_ALL=C apk info tailscale' and retry the update","If the format genuinely changed in your apk-tools version, update tailscale (newer parser) or file an issue with the exact line","As a workaround upgrade manually with 'sudo apk upgrade tailscale' - the hint from the deferred wrapper"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Sanity-check that apk's info output is parseable before updating.\nout, err := exec.Command(\"apk\", \"info\", \"tailscale\").CombinedOutput()\nif err != nil {\n    return err\n}\nfound := false\nfor _, line := range strings.Split(string(out), \"\\n\") {\n    line = strings.TrimSpace(line)\n    if strings.HasPrefix(line, \"tailscale-\") && len(strings.SplitN(line, \"-\", 3)) >= 3 {\n        found = true\n    }\n}\nif !found {\n    return errors.New(\"apk info output has no parseable tailscale version line\")\n}","typeGuard":null,"tryCatchPattern":"if err := up.Update(); err != nil {\n    if strings.Contains(err.Error(), \"failed to parse latest version from\") {\n        // run 'LC_ALL=C apk info tailscale' and compare the line shape;\n        // fall back to instructing a manual 'apk upgrade tailscale'\n    }\n}","preventionTips":["Set LC_ALL=C in automation environments for stable command output","Pin the apk-tools version in images so output format is predictable","Report format changes upstream so the parser tracks apk-tools"],"tags":["linux","alpine","apk","parsing","version-resolution"],"backgroundTag":null,"analyzedSha":"cfe32b8be6a33f8e24fbc369cbfbf7c729d9e042","analyzedAt":"2026-08-15T19:58:31.583Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}