v2rayA/v2rayA · error
tinytun route script (%s): %w
Error message
tinytun route script (%s): %w
What it means
runTinyTunScript wraps errors from resolveShellInfo with the stage name (e.g. pre/post route change) to give context about which script invocation failed. It means the shell type/path configured for tinytun route scripts could not be resolved into an executable spec (empty custom path or unknown shell type). No command was attempted yet.
Source
Thrown at service/kernel/v2ray/tinytun_enabled.go:729
case "cmd":
return shellInfo{bin: "cmd.exe", scriptFlag: "/C", ext: ".bat"}, nil
case "git_bash":
return shellInfo{bin: "bash.exe", ext: ".sh"}, nil
default:
return shellInfo{}, fmt.Errorf("unknown shell type: %v", shellType)
}
}
// runTinyTunScript writes the given script to a temp file and executes it
// with the configured shell. stage is only used for logging.
func runTinyTunScript(stage, script string) error {
if strings.TrimSpace(script) == "" {
return nil
}
setting := configure.GetSettingNotNil()
si, err := resolveShellInfo(setting.TunRouteShellType, setting.TunRouteShellPath)
if err != nil {
return fmt.Errorf("tinytun route script (%s): %w", stage, err)
}
// Resolve the shell binary via PATH if it is not an absolute path.
binPath := si.bin
if !filepath.IsAbs(binPath) {
if resolved, err := exec.LookPath(binPath); err == nil {
binPath = resolved
}
}
// Write script to a temp file with restricted permissions.
tmpFile, err := os.CreateTemp("", "tinytun_*"+si.ext)
if err != nil {
return fmt.Errorf("tinytun route script (%s): failed to create temp file: %w", stage, err)
}
defer os.Remove(tmpFile.Name())
// Restrict permissions immediately after creation (before writing content).View on GitHub (pinned to 71e5442fc5)
Solutions
- Inspect the inner error in the %w chain: 'custom shell path is empty' → set the path; 'unknown shell type' → use a supported value.
- Correct TunRouteShellType/TunRouteShellPath in settings.
- Disable the tun route script for that stage if scripts are not needed.
Defensive patterns
Strategy: validation
Validate before calling
si, err := resolveShellInfo(setting.TunRouteShellType, setting.TunRouteShellPath)
if err != nil {
return fmt.Errorf("tun route script disabled: %w", err)
}
if _, err := exec.LookPath(si.bin); err != nil {
return fmt.Errorf("shell %q not found in PATH", si.bin)
} Try / catch
if err := runTinyTunScript(stage, script); err != nil {
log.Warnf("%v — skipping route script", err)
return nil // degrade gracefully, keep tunnel running
} Prevention
- Validate shell settings at save time, not at script-run time
- Keep TunRouteShellPath absolute when using custom shells
- Check the inner resolveShellInfo error to know which fix applies
- Skip route scripts gracefully when shell config is invalid
When it happens
Trigger: runTinyTunScript at tinytun_enabled.go:729 calls resolveShellInfo(setting.TunRouteShellType, setting.TunRouteShellPath) and receives an error — custom shell with empty path, or unknown shellType string.
Common situations: Same root causes as the underlying resolveShellInfo errors: blank custom shell path, misspelled or unsupported shell type in settings; surfacing after a tun route change triggers a script run.
Related errors
- custom shell path is empty
- unknown shell type: %v
- failed to marshal tinytun config: %w
- failed to write tinytun config to %v: %w
- tinytun route script (%s) exited with error: %w
AI-assisted analysis of v2rayA/v2rayA@71e5442fc5 (2026-09-05).
Data as JSON: /api/errors/29ce812b46dba296.
Report an issue: GitHub.