{"record":{"id":"69d92a095242b470","repo":"grafana/k6","slug":"unmarshaling-hosts-option-w","errorCode":null,"errorMessage":"unmarshaling hosts option: %w","messagePattern":"unmarshaling hosts option: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/chromium/browser_type.go","lineNumber":537,"sourceCode":"\n\t// Add the host resolver rules.\n\t//\n\t// This is done by marshaling the k6 hosts option to JSON and then\n\t// unmarshaling it to a map[string]string. This is done because the\n\t// k6 v0.42 changed Hosts from a map to types.NullHosts and doesn't\n\t// expose the map anymore.\n\t//\n\t// TODO: A better way to do this would be to handle the resolver\n\t// rules by communicating with Chromium (and then using Hosts's\n\t// Match method) instead of passing the rules via the command line\n\t// to Chromium.\n\tvar rules map[string]string\n\tb, err := json.Marshal(k6opts.Hosts)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"marshaling hosts option: %w\", err)\n\t}\n\tif err := json.Unmarshal(b, &rules); err != nil {\n\t\treturn fmt.Errorf(\"unmarshaling hosts option: %w\", err)\n\t}\n\tfor k, v := range rules {\n\t\thostResolver = append(hostResolver, fmt.Sprintf(\"MAP %s %s\", k, v))\n\t}\n\tif len(hostResolver) > 0 {\n\t\tsort.Strings(hostResolver)\n\t\tflags[\"host-resolver-rules\"] = strings.Join(hostResolver, \",\")\n\t}\n\n\treturn nil\n}\n\n// makeLogger makes and returns an extension wide logger.\nfunc makeLogger(ctx context.Context, envLookup env.LookupFunc) (*log.Logger, error) {\n\tvar (\n\t\tk6Logger = k6ext.GetVU(ctx).State().Logger\n\t\tlogger   = log.New(k6Logger, common.GetIterationID(ctx))\n\t)","sourceCodeStart":519,"sourceCodeEnd":555,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/chromium/browser_type.go#L519-L555","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nexport const options = { hosts: { 'test.k6.io': 3000 } };\n\n// after\nexport const options = { hosts: { 'test.k6.io': 'localhost:3000' } };","handlingStrategy":"validation","validationCode":"const hosts = { 'test.k6.io': 'localhost:3000' };\nfor (const [k, v] of Object.entries(hosts)) {\n  if (typeof v !== 'string' || !/^[^:]+:\\d+$/.test(v)) {\n    throw new Error(`hosts['${k}'] must be a 'host:port' string, got: ${JSON.stringify(v)}`);\n  }\n}","typeGuard":"function isHostPortString(v) {\n  return typeof v === 'string' && /^[^:\\s]+:\\d+$/.test(v);\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["launch","hosts-option","configuration","json"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}