{"record":{"id":"a645047edfde4e33","repo":"grafana/k6","slug":"invalid-timeout-value-w","errorCode":null,"errorMessage":"invalid timeout value: %w","messagePattern":"invalid timeout value: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/grpc/params.go","lineNumber":60,"sourceCode":"\tfor _, k := range params.Keys() {\n\t\tswitch k {\n\t\tcase \"metadata\":\n\t\t\tmd, err := newMetadata(params.Get(k))\n\t\t\tif err != nil {\n\t\t\t\treturn result, fmt.Errorf(\"invalid metadata param: %w\", err)\n\t\t\t}\n\n\t\t\tresult.Metadata = md\n\t\tcase \"tags\":\n\t\t\tif err := common.ApplyCustomUserTags(rt, &result.TagsAndMeta, params.Get(k)); err != nil {\n\t\t\t\treturn result, fmt.Errorf(\"metric tags: %w\", err)\n\t\t\t}\n\t\tcase \"timeout\":\n\t\t\tvar err error\n\t\t\tv := params.Get(k).Export()\n\t\t\tresult.Timeout, err = types.GetDurationValue(v)\n\t\t\tif err != nil {\n\t\t\t\treturn result, fmt.Errorf(\"invalid timeout value: %w\", err)\n\t\t\t}\n\t\tcase \"discardResponseMessage\":\n\t\t\tresult.DiscardResponseMessage = params.Get(k).ToBoolean()\n\t\tdefault:\n\t\t\treturn result, fmt.Errorf(\"unknown param: %q\", k)\n\t\t}\n\t}\n\n\treturn result, nil\n}\n\n// newMetadata constructs a metadata.MD from the input value.\nfunc newMetadata(input sobek.Value) (metadata.MD, error) {\n\tmd := metadata.New(nil)\n\n\tif common.IsNullish(input) {\n\t\treturn md, nil\n\t}","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/grpc/params.go#L42-L78","documentation":"The timeout key in call params (client.invoke() / new grpc.Stream()) is converted with types.GetDurationValue (lib/types/types.go:197): numbers are treated as milliseconds, strings must be valid duration literals such as '500ms' or '2s', and every other JS type (object, boolean, array) or malformed string errors out as 'invalid timeout value'.","triggerScenarios":"{ timeout: true }; { timeout: {} }; { timeout: 'fast' }; { timeout: '1sec' } (unknown unit); { timeout: '10 seconds' } (spaces not allowed).","commonSituations":"Env-provided timeouts with human-readable units; config values expressed in seconds passed as bare numbers and silently interpreted as milliseconds; copy-paste of HTTP timeout formats.","solutions":["Use a string like '10s' or a millisecond number like 10000","For env config, parse explicitly: parseInt(__ENV.TIMEOUT_MS, 10)","If config stores seconds, multiply by 1000 before passing"],"exampleFix":"// before\nclient.invoke(method, req, { timeout: '10 sec' });\n\n// after\nclient.invoke(method, req, { timeout: '10s' });","handlingStrategy":"validation","validationCode":"const DURATION_RE = /^\\d+(\\.\\d+)?(ns|us|ms|s|m|h)$/;\nfunction isDurationValue(v) {\n  return typeof v === 'number' || (typeof v === 'string' && DURATION_RE.test(v));\n}\nif (params.timeout != null && !isDurationValue(params.timeout)) {\n  throw new Error(`invalid timeout: ${params.timeout} (use '10s' or milliseconds)`);\n}\nclient.invoke(method, req, params);","typeGuard":"function isDurationValue(v) {\n  return typeof v === 'number' || (typeof v === 'string' && /^\\d+(\\.\\d+)?(ns|us|ms|s|m|h)$/.test(v));\n}","tryCatchPattern":null,"preventionTips":["Prefer '10s'-style strings over bare numbers to avoid ms/s ambiguity","Parse env-provided durations once in init instead of passing raw strings","Unit-test shared param helpers with both accepted forms"],"tags":["grpc","timeout","duration","params"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}