{"record":{"id":"9c61bd1efd17f092","repo":"grafana/k6","slug":"unmarshaling-q-to-colorscheme-w","errorCode":null,"errorMessage":"unmarshaling %q to ColorScheme: %w","messagePattern":"unmarshaling %q to ColorScheme: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/page.go","lineNumber":169,"sourceCode":"\t\"light\":         ColorSchemeLight,\n\t\"dark\":          ColorSchemeDark,\n\t\"no-preference\": ColorSchemeNoPreference,\n}\n\n// MarshalJSON marshals the enum as a quoted JSON string.\nfunc (c ColorScheme) MarshalJSON() ([]byte, error) {\n\tbuffer := bytes.NewBufferString(`\"`)\n\tbuffer.WriteString(colorSchemeToString[c])\n\tbuffer.WriteString(`\"`)\n\treturn buffer.Bytes(), nil\n}\n\n// UnmarshalJSON unmarshals a quoted JSON string to the enum value.\nfunc (c *ColorScheme) UnmarshalJSON(b []byte) error {\n\tvar j string\n\terr := json.Unmarshal(b, &j)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unmarshaling %q to ColorScheme: %w\", b, err)\n\t}\n\t// Note that if the string cannot be found then it will be set to the zero value.\n\t*c = colorSchemeToID[j]\n\treturn nil\n}\n\n// EmulatedSize represents the emulated viewport and screen sizes.\ntype EmulatedSize struct {\n\tViewport Viewport\n\tScreen   Screen\n}\n\n// NewEmulatedSize creates and returns a new EmulatedSize.\nfunc NewEmulatedSize(viewport Viewport, screen Screen) *EmulatedSize {\n\treturn &EmulatedSize{\n\t\tViewport: viewport,\n\t\tScreen:   screen,\n\t}","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/page.go#L151-L187","documentation":"ColorScheme.UnmarshalJSON tried to json.Unmarshal the raw bytes into a Go string and failed — the value for the colorScheme option is not a JSON string. As with ReducedMotion, an unknown string quietly becomes the zero value ('no-preference'); the error only fires for non-string JSON (numbers, booleans, objects, malformed input).","triggerScenarios":"Passing colorScheme as a non-string to browser.newContext/newPage, e.g. colorScheme: 0, colorScheme: ['dark'], or an object; or supplying the option through serialized JSON config where it lost its string type.","commonSituations":"Dynamic option generation that inserts constants/numbers; config files where quotes were stripped; ported Playwright scripts using different enum representations.","solutions":["Use the string values 'light', 'dark', or 'no-preference' for colorScheme","Check the serialized form (k6 inspect) if options flow in from --config or env","Add a small assert in the script that typeof options-browser colorScheme is 'string' before creating the context"],"exampleFix":"// before\nconst ctx = browser.newContext({ colorScheme: 2 }); // not a string\n\n// after\nconst ctx = browser.newContext({ colorScheme: 'dark' });","handlingStrategy":"type-guard","validationCode":"const cs = opts.colorScheme;\nif (cs !== undefined && typeof cs !== 'string') { throw new TypeError('colorScheme must be a string: \"light\" | \"dark\" | \"no-preference\"'); }","typeGuard":"function isValidColorScheme(v) {\n  return v === undefined || v === 'light' || v === 'dark' || v === 'no-preference';\n}","tryCatchPattern":null,"preventionTips":["Pass colorScheme as a string literal: 'light', 'dark', or 'no-preference'","Validate serialized option sources (config files, env vars) for type, not just presence","Unknown strings silently fall back to 'no-preference' — assert the exact value you intend"],"tags":["browser","options","json","enum","validation"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}