shadow1ng/fscan · error

parser_invalid_start_ip

Error message

parser_invalid_start_ip

What it means

The start portion of an IP range string failed net.ParseIP. newRangeHostSource trims the text before the dash and requires it to be a valid IP literal; anything else (hostname, octet out of range like 300.1.1.1, empty string) yields this message naming the bad start value.

Source

Thrown at common/parsers/host_iterator.go:354

	end := start + uint32(size-1)
	if size > 2 {
		start++
		end--
	}
	return &cidrHostSource{current: start, end: end}, nil
}

func newRangeHostSource(rangeStr string) (hostSource, error) {
	parts := strings.Split(rangeStr, "-")
	if len(parts) != 2 {
		return nil, fmt.Errorf("%s", i18n.Tr("parser_invalid_ip_range_fmt", rangeStr))
	}

	startIPStr := strings.TrimSpace(parts[0])
	endIPStr := strings.TrimSpace(parts[1])
	startIP := net.ParseIP(startIPStr)
	if startIP == nil {
		return nil, fmt.Errorf("%s", i18n.Tr("parser_invalid_start_ip", startIPStr))
	}

	if len(endIPStr) < 4 || !strings.Contains(endIPStr, ".") {
		endNum, err := strconv.Atoi(endIPStr)
		if err != nil || endNum > 255 {
			return nil, fmt.Errorf("%s", i18n.Tr("parser_invalid_ip_end_val", endIPStr))
		}
		parts := strings.Split(startIPStr, ".")
		if len(parts) != 4 {
			return nil, fmt.Errorf("%s", i18n.Tr("parser_invalid_ip_fmt", startIPStr))
		}
		parts[3] = strconv.Itoa(endNum)
		endIPStr = strings.Join(parts, ".")
	}

	start, ok := ipToUint32(startIP)
	if !ok {
		return nil, fmt.Errorf("%s", i18n.GetText("parser_ipv4_only"))

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Correct the start IP so net.ParseIP accepts it, e.g. "192.168.1.10-192.168.1.20".
  2. Validate with net.ParseIP(strings.TrimSpace(start)) != nil in config-loading code before calling addRange.
  3. If a hostname is intended, resolve it with net.LookupHost first and use the returned IP.

Example fix

// before
m.AddRange("192.168.1.256-192.168.1.260") // parser_invalid_start_ip

// after
start := net.ParseIP("192.168.1.250")
if start == nil { return fmt.Errorf("bad start IP") }
m.AddRange("192.168.1.250-192.168.1.260")
Defensive patterns

Strategy: validation

Validate before calling

func validStartIP(rng string) bool {
    parts := strings.SplitN(rng, "-", 2)
    if len(parts) != 2 {
        return false
    }
    return net.ParseIP(strings.TrimSpace(parts[0])) != nil
}

Try / catch

if err := matcher.AddRange(rng); err != nil {
    return fmt.Errorf("range %q rejected: %w", rng, err)
}

Prevention

When it happens

Trigger: addRange/newHostSource with "example.com-10.0.0.5", "300.0.0.1-10.0.0.2", "-10.0.0.5", or any non-IP text left of the dash.

Common situations: Users entering hostnames instead of IPs; mistyped octets (e.g. 192.168.1.256); whitespace or invisible characters from YAML/CSV fields that TrimSpace does not remove (e.g. NBSP).

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of shadow1ng/fscan@95cc12e753 (2026-09-06). Data as JSON: /api/errors/ebeb661f4c4ede36. Report an issue: GitHub.