grafana/k6 · error
unmarshaling hosts option: %w
Error message
unmarshaling hosts option: %w
What it means
Returned by setFlagsFromK6Options when the JSON produced from options.Hosts cannot be unmarshaled into map[string]string. Because the code round-trips Hosts through JSON (k6 v0.42 hid the internal map), any hosts entry whose value is not a plain string (e.g. a number, array, or object) fails here, before --host-resolver-rules can be built for Chrome.
Source
Thrown at internal/js/modules/k6/browser/chromium/browser_type.go:537
// Add the host resolver rules.
//
// This is done by marshaling the k6 hosts option to JSON and then
// unmarshaling it to a map[string]string. This is done because the
// k6 v0.42 changed Hosts from a map to types.NullHosts and doesn't
// expose the map anymore.
//
// TODO: A better way to do this would be to handle the resolver
// rules by communicating with Chromium (and then using Hosts's
// Match method) instead of passing the rules via the command line
// to Chromium.
var rules map[string]string
b, err := json.Marshal(k6opts.Hosts)
if err != nil {
return fmt.Errorf("marshaling hosts option: %w", err)
}
if err := json.Unmarshal(b, &rules); err != nil {
return fmt.Errorf("unmarshaling hosts option: %w", err)
}
for k, v := range rules {
hostResolver = append(hostResolver, fmt.Sprintf("MAP %s %s", k, v))
}
if len(hostResolver) > 0 {
sort.Strings(hostResolver)
flags["host-resolver-rules"] = strings.Join(hostResolver, ",")
}
return nil
}
// makeLogger makes and returns an extension wide logger.
func makeLogger(ctx context.Context, envLookup env.LookupFunc) (*log.Logger, error) {
var (
k6Logger = k6ext.GetVU(ctx).State().Logger
logger = log.New(k6Logger, common.GetIterationID(ctx))
)View on GitHub (pinned to 93accf6570)
Solutions
- Make every hosts value a string of the form 'host:port': hosts: { 'test.k6.io': 'localhost:3000' }
- Quote values in YAML/JSON config files so they stay strings
- Validate the hosts object before k6 run if generating scripts dynamically
- Remove hosts temporarily to confirm launch succeeds, then add mappings back one at a time
Example fix
// before
export const options = { hosts: { 'test.k6.io': 3000 } };
// after
export const options = { hosts: { 'test.k6.io': 'localhost:3000' } }; Defensive patterns
Strategy: validation
Validate before calling
const hosts = { 'test.k6.io': 'localhost:3000' };
for (const [k, v] of Object.entries(hosts)) {
if (typeof v !== 'string' || !/^[^:]+:\d+$/.test(v)) {
throw new Error(`hosts['${k}'] must be a 'host:port' string, got: ${JSON.stringify(v)}`);
}
} Type guard
function isHostPortString(v) {
return typeof v === 'string' && /^[^:\s]+:\d+$/.test(v);
} Prevention
- Quote hosts values in YAML/JSON so they stay strings
- Never use bare port numbers as hosts values
- Validate the hosts block with a lint step when scripts are generated
When it happens
Trigger: Launching with options.hosts containing non-string values, e.g. hosts: { 'example.com': 8080 } or a nested object; values that serialize as JSON objects/arrays instead of 'host:port' strings.
Common situations: Script authors writing a port number instead of a full 'host:port' value; copy-pasted hosts blocks from other tools with different value formats; YAML configs where quoting turns values into unexpected types.
Related errors
- marshaling hosts option: %w
- parsing options from script got error while parsing %q: %w
- finding browser executable: %w
- k6 couldn't detect google chrome or a chromium-supported bro
- invalid browser command line flag: "%s=%v"
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/69d92a095242b470.
Report an issue: GitHub.