tailscale/tailscale · error
failed to find latest Tailscale version in /boot/config/plug
Error message
failed to find latest Tailscale version in /boot/config/plugins/tailscale.plg: %w
What it means
updateUnraid then calls parseUnraidPluginVersion on /tmp/plugins/tailscale.plg (where 'plugin check' stages pending .plg files — the error text names /boot/config/plugins but the code reads /tmp per the comment). The wrapped error is either an os.ReadFile failure (file missing/unreadable) or 'version not found in plg file' when the regexp for <FILE Name="/boot/config/plugins/tailscale/tailscale_(\d+\.\d+\.\d+)_[a-z0-9]+.tgz"> does not match.
Source
Thrown at clientupdate/clientupdate.go:1217
}
}()
// We need to run `plugin check` for the latest tailscale.plg to get
// downloaded. Unfortunately, the output of this command does not contain
// the latest tailscale version available. So we'll parse the downloaded
// tailscale.plg file manually below.
out, err := exec.Command("plugin", "check", "tailscale.plg").CombinedOutput()
if err != nil {
return fmt.Errorf("failed to check if Tailscale plugin is upgradable: %w, output: %q", err, out)
}
// Note: 'plugin check' downloads plugins to /tmp/plugins.
// The installed .plg files are in /boot/config/plugins/, but the pending
// ones are in /tmp/plugins. We should parse the pending file downloaded by
// 'plugin check'.
latest, err := parseUnraidPluginVersion("/tmp/plugins/tailscale.plg")
if err != nil {
return fmt.Errorf("failed to find latest Tailscale version in /boot/config/plugins/tailscale.plg: %w", err)
}
if !up.confirm(latest) {
return nil
}
up.Logf("c2n: running 'plugin update tailscale.plg'")
cmd := exec.Command("plugin", "update", "tailscale.plg")
cmd.Stdout = up.Stdout
cmd.Stderr = up.Stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed tailscale plugin update: %w", err)
}
return nil
}
func parseUnraidPluginVersion(plgPath string) (string, error) {
plg, err := os.ReadFile(plgPath)
if err != nil {View on GitHub (pinned to cfe32b8be6)
Solutions
- Inspect the staged file manually: cat /tmp/plugins/tailscale.plg and look for the <FILE Name=...> line
- Re-run 'plugin check tailscale.plg' and immediately retry the update so /tmp content is fresh
- If the FILE line format changed, update manually (plugin check tailscale.plg && plugin update tailscale.plg) and report the format change upstream
- Check /tmp is writable and was not wiped mid-update
Defensive patterns
Strategy: validation
Validate before calling
// Verify the staged .plg file exists and parses before updating
func unraidPlgStaged() (string, bool) {
plg, err := os.ReadFile("/tmp/plugins/tailscale.plg")
if err != nil { return "", false }
m := regexp.MustCompile(`<FILE Name="/boot/config/plugins/tailscale/tailscale_(\d+\.\d+\.\d+)_[a-z0-9]+\.tgz">`).FindStringSubmatch(string(plg))
if len(m) < 2 { return "", false }
return m[1], true
} Type guard
func isPlgVersionParseErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "failed to find latest Tailscale version in /boot/config/plugins/tailscale.plg")
} Try / catch
if err := up.Update(ctx); err != nil {
if isPlgVersionParseErr(err) {
// re-stage the descriptor then retry: plugin check downloads it to /tmp/plugins
if cerr := exec.Command("plugin", "check", "tailscale.plg").Run(); cerr == nil {
return up.Update(ctx)
}
}
return err
} Prevention
- Run 'plugin check tailscale.plg' immediately before the update so /tmp/plugins content is fresh
- Do not clean /tmp while an update is in flight on Unraid
- If the .plg filename format changes upstream, update the manual runbook: plugin check && plugin update still works without parsing
When it happens
Trigger: 'plugin check' exited 0 but wrote no tailscale.plg into /tmp/plugins (output went elsewhere or /tmp was cleared between steps), or the .plg file's FILE line changed shape so the version regex misses (layout change in a newer Tailscale .plg).
Common situations: /tmp on tmpfs cleared by another process between download and parse; Unraid version differences staging plugins in another directory; Tailscale .plg template updated with a different filename pattern.
Related errors
- version not found in plg file
- installing a specific version on Unraid is not supported
- failed to check if Tailscale is upgradable using qpkg_cli, o
- %w; you can try updating using "plugin check tailscale.plg &
- failed to check if Tailscale plugin is upgradable: %w, outpu
AI-assisted analysis of tailscale/tailscale@cfe32b8be6 (2026-08-15).
Data as JSON: /api/errors/64eaa1a3be7542b4.
Report an issue: GitHub.