ginuerzh/gost · error

hosts list must look like google.pl,*.google.com given: %s

Error message

hosts list must look like google.pl,*.google.com given: %s

What it means

ParsePermissions validates each permission entry of the form [actions]:[hosts]:[ports]. The hosts segment must be a non-empty comma-separated string; when ParseStringSet rejects it (most commonly because it is empty), the parser wraps the failure in this error and aborts, returning no Permissions at all. This is a fail-fast config validation error, not a runtime condition.

Source

Thrown at permissions.go:159

	}

	perms := strings.Split(s, " ")

	for _, perm := range perms {
		parts := strings.Split(perm, ":")

		switch len(parts) {
		case 3:
			actions, err := ParseStringSet(parts[0])

			if err != nil {
				return nil, fmt.Errorf("action list must look like connect,bind given: %s", parts[0])
			}

			hosts, err := ParseStringSet(parts[1])

			if err != nil {
				return nil, fmt.Errorf("hosts list must look like google.pl,*.google.com given: %s", parts[1])
			}

			ports, err := ParsePortSet(parts[2])

			if err != nil {
				return nil, fmt.Errorf("ports list must look like 80,8000-9000, given: %s", parts[2])
			}

			permission := Permission{Actions: *actions, Hosts: *hosts, Ports: *ports}

			*ps = append(*ps, permission)
		default:
			return nil, fmt.Errorf("permission must have format [actions]:[hosts]:[ports] given: %s", perm)
		}
	}

	return ps, nil
}

View on GitHub (pinned to a33fdbf4c9)

Solutions

  1. Check the permission string at permissions.go:159 — the hosts segment (parts[1]) must be a non-empty comma-separated list like google.pl,*.google.com
  2. Fix malformed input: replace "connect::80" with "connect:google.pl:80"
  3. Collapse double spaces in the permissions string; ParsePermissions splits on a single space so extra spaces introduce empty tokens that fail parsing
  4. Validate the format with a regex before calling ParsePermissions

Example fix

// before
perms, err := gost.ParsePermissions("connect::8080")
// after
perms, err := gost.ParsePermissions("connect:*.example.com:8080")
Defensive patterns

Strategy: validation

Validate before calling

func validPerms(s string) bool {
    for _, perm := range strings.Fields(s) {
        parts := strings.Split(perm, ":")
        if len(parts) != 3 || parts[0] == "" || parts[1] == "" {
            return false
        }
    }
    return true
}
if !validPerms(input) { return errors.New("bad permissions string") }

Type guard

func isNonEmptyStringSet(s string) bool { return s != "" }

Try / catch

perms, err := gost.ParsePermissions(input)
if err != nil {
    if strings.Contains(err.Error(), "hosts list must look like") {
        log.Fatalf("bad hosts segment in permission %q: %v", input, err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling ParsePermissions with a permission whose middle colon-separated field is empty or invalid, e.g. "connect::80" — a permission token whose parts[1] is empty fails ParseStringSet ("cannot be empty").

Common situations: Gost config files or command-line permission flags with typos: a colon typo, double spaces between permissions (strings.Split on a single space yields empty tokens), trailing colons, or an empty hosts field like "connect::443" pasted from documentation.

Related errors


AI-assisted analysis of ginuerzh/gost@a33fdbf4c9 (2026-09-02). Data as JSON: /api/errors/4cfea66d7096da2a. Report an issue: GitHub.