AlexxIT/go2rtc · error

pinggy: unsupported proto

Error message

pinggy: unsupported proto: ${proto}

What it means

NewClient validates the tunnel protocol string before creating the SSH-based pinggy client. Only "http", "tcp", "tls" and "tlstcp" are accepted; an empty string defaults to "http". Anything else throws this error.

Solutions

  1. Use one of: "http", "tcp", "tls", "tlstcp"
  2. Pass "" to default to "http"
  3. Normalize/validate user input case before calling NewClient

Example fix

// before
c, err := pinggy.NewClient("https")
// after
c, err := pinggy.NewClient("tls")
Defensive patterns

Strategy: validation

Validate before calling

var validProtos = map[string]bool{"http": true, "tcp": true, "tls": true, "tlstcp": true, "": true}
if !validProtos[proto] {
    return fmt.Errorf("proto must be http|tcp|tls|tlstcp, got %q", proto)
}

Try / catch

c, err := pinggy.NewClient(proto)
if err != nil && strings.Contains(err.Error(), "unsupported proto") {
    c, err = pinggy.NewClient("") // default to http
}

Prevention

When it happens

Trigger: Calling NewClient (via proxy) with proto values like "https", "ssh", "UDP", or any string not in the allowed set.

Common situations: Passing "https" thinking TLS tunnel means https; case mistakes like "HTTP"; copying proto names from other tunnel tools.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.


AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07). Data as JSON: /api/errors/88fb30478a6f6b96. Report an issue: GitHub.

Appendix: source

Thrown at pkg/pinggy/pinggy.go:27

	"net/http"
	"time"

	"golang.org/x/crypto/ssh"
)

type Client struct {
	SSH *ssh.Client
	TCP net.Listener
	API *http.Client
}

func NewClient(proto string) (*Client, error) {
	switch proto {
	case "http", "tcp", "tls", "tlstcp":
	case "":
		proto = "http"
	default:
		return nil, errors.New("pinggy: unsupported proto: " + proto)
	}

	config := &ssh.ClientConfig{
		User:            "auth+" + proto,
		Auth:            []ssh.AuthMethod{ssh.Password("nopass")},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
		Timeout:         5 * time.Second,
	}

	client, err := ssh.Dial("tcp", "a.pinggy.io:443", config)
	if err != nil {
		return nil, err
	}

	ln, err := client.Listen("tcp", "0.0.0.0:0")
	if err != nil {
		_ = client.Close()
		return nil, err

View on GitHub (pinned to c245815e75)