{"record":{"id":"56ecfb38ea415d36","repo":"grafana/k6","slug":"parsing-ttl-w","errorCode":null,"errorMessage":"parsing TTL: %w","messagePattern":"parsing TTL: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/network_manager.go","lineNumber":169,"sourceCode":"\t\t\"connectionaborted\":    network.ErrorReasonConnectionAborted,\n\t\t\"connectionclosed\":     network.ErrorReasonConnectionClosed,\n\t\t\"connectionfailed\":     network.ErrorReasonConnectionFailed,\n\t\t\"connectionrefused\":    network.ErrorReasonConnectionRefused,\n\t\t\"connectionreset\":      network.ErrorReasonConnectionReset,\n\t\t\"internetdisconnected\": network.ErrorReasonInternetDisconnected,\n\t\t\"namenotresolved\":      network.ErrorReasonNameNotResolved,\n\t\t\"timedout\":             network.ErrorReasonTimedOut,\n\t\t\"failed\":               network.ErrorReasonFailed,\n\t}\n}\n\n// Returns a new Resolver.\n// Copied with minor changes from\n// https://github.com/grafana/k6/blob/fb70bc6f3d3f22a40e65f32deea3cea1b6d70a76/js/runner.go#L459\nfunc newResolver(conf k6types.DNSConfig) (k6netext.Resolver, error) {\n\tttl, err := parseTTL(conf.TTL.String)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"parsing TTL: %w\", err)\n\t}\n\n\tdnsSel := conf.Select\n\tif !dnsSel.Valid {\n\t\tdnsSel = k6types.DefaultDNSConfig().Select\n\t}\n\tdnsPol := conf.Policy\n\tif !dnsPol.Valid {\n\t\tdnsPol = k6types.DefaultDNSConfig().Policy\n\t}\n\treturn k6netext.NewResolver(\n\t\tnet.LookupIP, ttl, dnsSel.DNSSelect, dnsPol.DNSPolicy), nil\n}\n\n// Parse a string representation of TTL to time.Duration.\n// Copied from https://github.com/grafana/k6/blob/fb70bc6f3d3f22a40e65f32deea3cea1b6d70a76/js/runner.go#L479\nfunc parseTTL(ttlS string) (time.Duration, error) {\n\tttl := time.Duration(0)","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/network_manager.go#L151-L187","documentation":"Intermediate wrap in newResolver: the k6types-based parseTTL helper rejected the dns.ttl string from options. It appears inside the chain 'newResolver(...): parsing TTL: invalid DNS TTL: <value>' whenever a new browser page/context is created, pointing squarely at the test's DNS configuration.","triggerScenarios":"Browser page creation with options.dns.ttl set to a string that is not '0', 'inf', empty, or parseable by ParseExtendedDuration (typos, unknown units, negative values, comma-separated lists).","commonSituations":"Copy-pasted options from k6 HTTP tests using TTL lists; CI injecting options via --config or environment (K6_DNS_TTL) with a bad value; unit mismatch after editing '600s' to '10m' style values by hand.","solutions":["Fix options.dns.ttl to a single valid duration or '0'/'inf'","Check overridden config sources: --config file, K6_DNS_TTL env var, cloud-originated options","Rule out list syntax ('1m,5m') which is unsupported here","Re-run with a minimal script to confirm the dns block is the culprit"],"exampleFix":"# before\nK6_DNS_TTL='1m,5m' k6 run script.js\n\n# after\nK6_DNS_TTL='1m' k6 run script.js","handlingStrategy":"validation","validationCode":"const m = /newResolver\\(.*parsing TTL: invalid DNS TTL: (.+)/.exec(err.message);\nif (m) throw new Error(`fix options.dns.ttl: '${m[1]}' is not 0|inf|<duration>`);","typeGuard":"function isValidTtl(v) {\n  return v === '0' || v === 'inf' || /^\\d+(\\.\\d+)?(ms|s|m|h)$/.test(v);\n}","tryCatchPattern":null,"preventionTips":["Audit --config files and K6_DNS_TTL in CI for list syntax","Unit-check option generation when templating scripts","Note empty ttl is valid (default applied); lists are not"],"tags":["browser","dns","config","ttl"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}