urbanadventurer/WhatWeb · error
Unable to parse invalid target. No hostname.
Error message
Unable to parse invalid target. No hostname.
What it means
make_target_list validates each target string by parsing it with Addressable::URI. If parsing succeeds but the resulting URI has an empty host (no hostname), WhatWeb raises 'Unable to parse invalid target. No hostname.' because it cannot resolve or connect to a target without a host.
Solutions
- Supply a full target with a hostname, e.g. http://example.com/ or example.com
- Pre-validate each target: Addressable::URI.parse(x) and check !domain.host.to_s.empty? before running
- Trim and skip empty/blank lines when reading targets from a file (x.split(/\s+/).reject(&:empty?))
- If the target was meant to be a local file or IP range, use the appropriate input form rather than a bare path string
Example fix
// before whatweb /admin/login.php // after whatweb http://example.com/admin/login.php
Defensive patterns
Strategy: validation
Validate before calling
require 'addressable/uri' def has_hostname?(s) uri = Addressable::URI.parse(s.to_s) !uri.host.to_s.empty? rescue Addressable::URI::InvalidURIError false end
Type guard
def valid_target?(s) s.is_a?(String) && !s.strip.empty? && has_hostname?(s) end
Try / catch
begin
WhatWeb::Scanner.new(targets)
rescue RuntimeError => e
raise unless e.message.include?('Unable to parse invalid target')
warn 'Every target needs a hostname, e.g. http://example.com'
end Prevention
- Always include scheme and host in targets (http://example.com)
- Filter blank lines and stray paths out of target files
- Validate each target with Addressable::URI.parse before running
- Confirm the value passed is a target, not a filename or flag argument
When it happens
Trigger: Passing a bare string without a host — e.g. '/path/only', 'http://', a stray filename or option value — into the target list so Addressable::URI.parse yields a URI with domain.host == '' or nil-adjacent emptiness.
Common situations: Operators forgetting the scheme+host (passing just a path); shell scripts passing empty strings from unset variables; target lists with blank lines or filenames accidentally included; ambiguity where the target regex matched a non-host string like an IP range fragment.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- You must specify the available versions of the product
- You must specify the available url of the website
- No target
- Error parsing target IP range: #
- Error: # is a directory
AI-assisted analysis of urbanadventurer/WhatWeb@d279d93042 (2026-09-15).
Data as JSON: /api/errors/8791c69a58a444f4.
Report an issue: GitHub.
Appendix: source
Thrown at lib/whatweb/scan.rb:281
original_hostname = x.dup
# Add HTTPS version
https_version = "https://#{x}"
push_to_urllist << https_version
# add HTTP prefix to current target
x.sub!(/^/, 'http://')
# Provide informational message to user
debug("Simple hostname detected: #{original_hostname}. Testing both HTTP and HTTPS.")
else
# For more complex paths, just use HTTP prefix as before
x.sub!(/^/, 'http://')
end
end
# is it a valid domain?
begin
domain = Addressable::URI.parse(x)
# check validity
raise 'Unable to parse invalid target. No hostname.' if domain.host.empty?
# convert IDN domain
x = domain.normalize.to_s if domain.host !~ %r{^[a-zA-Z0-9\.:/]*$}
# Reset counter on successful parse
consecutive_errors = 0
rescue => e
# Count consecutive errors
consecutive_errors += 1
# Abort after 10 consecutive parsing errors
if consecutive_errors >= 10
error("Aborting target processing after #{consecutive_errors} consecutive parsing errors.")
error("The input appears to contain invalid URLs or non-URL data.")
error("Please check your input and ensure it contains valid URLs.")
break
end
View on GitHub (pinned to d279d93042)