shadow1ng/fscan · error

parser_invalid_ip_fmt

Error message

parser_invalid_ip_fmt

What it means

When the short-tail branch rewrites the start IP's last octet, it requires the start string to contain exactly four dot-separated octets. If strings.Split(startIPStr, ".") yields anything other than 4 parts, this formatted message naming the start string is returned. Note startIP already parsed as an IP, so this mainly guards odd canonical forms before octet substitution.

Source

Thrown at common/parsers/host_iterator.go:364

	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"))
	}
	end, ok := ipToUint32(net.ParseIP(endIPStr))
	if !ok {
		return nil, fmt.Errorf("%s", i18n.Tr("parser_invalid_end_ip", endIPStr))
	}
	if start > end {
		return nil, fmt.Errorf("%s", i18n.GetText("parser_start_gt_end"))
	}
	return &cidrHostSource{current: start, end: end}, nil
}

View on GitHub (pinned to 95cc12e753)

Solutions

  1. Pass the start IP in standard dotted-quad form, e.g. "192.168.1.1-50".
  2. Normalize the string first: verify strings.Count(start, ".") == 3 before addRange.
  3. Avoid abbreviated IPv4 forms (e.g. "127.1") which net.ParseIP may accept but lack four dotted parts.

Example fix

// before
m.AddRange("192.168.1-50") // ambiguous; may hit parser_invalid_ip_fmt

// after
m.AddRange("192.168.0.1-50") // full dotted-quad start plus numeric tail
Defensive patterns

Strategy: validation

Validate before calling

func startIsDottedQuad(rng string) bool {
    parts := strings.SplitN(rng, "-", 2)
    if len(parts) != 2 {
        return false
    }
    return len(strings.Split(strings.TrimSpace(parts[0]), ".")) == 4
}

Try / catch

if err := matcher.AddRange(rng); err != nil {
    return fmt.Errorf("normalize %q to dotted-quad: %w", rng, err)
}

Prevention

When it happens

Trigger: addRange with a start IP that parses but does not have 4 dot-separated labels in its original string form combined with a numeric short tail, e.g. unusual formatting of the start portion in "ip-tail" notation.

Common situations: Programmatically generated range strings using abbreviated IP forms; localization/formatting layers that mangle dotted-quad strings before they reach addRange.

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/a30b57b94ebc3735. Report an issue: GitHub.