{"record":{"id":"602c3912325a952c","repo":"grafana/k6","slug":"marshaling-hosts-option-w","errorCode":null,"errorMessage":"marshaling hosts option: %w","messagePattern":"marshaling hosts option: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/js/modules/k6/browser/chromium/browser_type.go","lineNumber":534,"sourceCode":"\tif currHostResolver, ok := flags[\"host-resolver-rules\"]; ok {\n\t\thostResolver = append(hostResolver, fmt.Sprintf(\"%s\", currHostResolver))\n\t}\n\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 (","sourceCodeStart":516,"sourceCodeEnd":552,"githubUrl":"https://github.com/grafana/k6/blob/8d06114777191d21ef885d05c5f8aa9e1ed838ae/internal/js/modules/k6/browser/chromium/browser_type.go#L516-L552","documentation":"When the k6 browser module launches Chromium, it converts the k6 `hosts` option (types.NullHosts) into --host-resolver-rules by round-tripping it through JSON into a map[string]string. This error means json.Marshal of the hosts option failed at that conversion step. Because NullHosts marshals as a plain map[string]string, this failure is a defensive guard that is essentially unreachable on released k6 builds; seeing it usually indicates an internal type change between k6 versions or a broken custom build.","triggerScenarios":"Launching the browser while the k6 `hosts` option is set (options.hosts or K6_HOSTS), and the internal NullHosts value failing to serialize. Only realistic if the NullHosts type/MarshalJSON changed between mismatched k6 versions, or in a forked/custom build.","commonSituations":"Upgrading k6 across versions where the hosts option internal representation changed; running a custom xk6 build against an incompatible lib; practically never on stock releases.","solutions":["Re-run the same script with the hosts option removed to confirm the failure is hosts-specific","Verify hosts entries are simple \"hostname\": \"ip\" or \"hostname\": \"ip:port\" pairs in options.hosts / K6_HOSTS","Upgrade k6 to a single consistent version so lib/types and the browser module match","If it reproduces on stock k6, capture K6_BROWSER_LOG=debug output and report it upstream"],"exampleFix":"// before\nexport const options = { hosts: { 'test.k6.io': new Date() } }; // non-string value\n\n// after\nexport const options = { hosts: { 'test.k6.io': '1.2.3.4' } }; // plain host->ip mapping","handlingStrategy":"validation","validationCode":"// In the k6 script, validate hosts entries before the run starts\nexport function setup() {\n  const hosts = __ENV.K6_HOSTS || '';\n  for (const pair of hosts.split(',')) {\n    if (!pair) continue;\n    const [host, ip] = pair.split('=');\n    if (!host || !ip || !/^\\d+\\.\\d+\\.\\d+\\.\\d+(:\\d+)?$/.test(ip.trim())) {\n      throw new Error(`Invalid hosts entry: ${pair} (expected host=ip[:port])`);\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep hosts option values as plain strings: host -> ip or ip:port","Use one consistent k6 version for lib and browser module","Smoke-test the script with hosts disabled when diagnosing launch failures"],"tags":["hosts","options","json","browser","serialization"],"backgroundTag":"json-serialization-failed","analyzedSha":"8d06114777191d21ef885d05c5f8aa9e1ed838ae","analyzedAt":"2026-08-18T03:05:52.393Z","contentChangedAt":"2026-08-18T03:05:52.393Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}