{"record":{"id":"5a80baccbde103b2","repo":"gastownhall/beads","slug":"parse-s-w-5a80ba","errorCode":null,"errorMessage":"parse %s: %w","messagePattern":"parse (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/jira/tracker.go","lineNumber":146,"sourceCode":"\t\t\tt.priorityMap = priorityMap\n\t\t}\n\n\t\tconst customFieldPrefix = \"jira.custom_fields.\"\n\t\tcustomFields := make(map[string]interface{})\n\t\ttypeCustomFields := make(map[string]map[string]interface{})\n\t\tfor key, val := range allConfig {\n\t\t\tif !strings.HasPrefix(key, customFieldPrefix) || strings.TrimSpace(val) == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tsuffix := strings.TrimPrefix(key, customFieldPrefix)\n\t\t\tif suffix == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tparsed, err := parseJiraCustomFieldValue(val)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"parse %s: %w\", key, err)\n\t\t\t}\n\n\t\t\tparts := strings.SplitN(suffix, \".\", 2)\n\t\t\tif len(parts) == 2 {\n\t\t\t\tif parts[0] == \"\" || parts[1] == \"\" {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif typeCustomFields[parts[0]] == nil {\n\t\t\t\t\ttypeCustomFields[parts[0]] = make(map[string]interface{})\n\t\t\t\t}\n\t\t\t\ttypeCustomFields[parts[0]][parts[1]] = parsed\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tcustomFields[suffix] = parsed\n\t\t}\n\t\tif len(customFields) > 0 {\n\t\t\tt.customFields = customFields\n\t\t}","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/jira/tracker.go#L128-L164","documentation":"Init parses custom Jira field values from the tracker configuration. When a configured custom field value looks like a JSON object or array (starts with '{' or '['), it is passed through parseJiraCustomFieldValue, which json.Unmarshal's it. If the JSON is malformed, Init wraps the parse error with the offending field key so the user knows exactly which field entry is invalid.","triggerScenarios":"Calling jira Tracker.Init with a config where a custom field (key with a recognized custom-field suffix) has a value like '{invalid' or '[1,2' — trimmed non-empty, starts with '{' or '[', but fails json.Unmarshal.","commonSituations":"Hand-edited config files where braces/quotes were dropped; shell/CI templating that mangled JSON; pasting a field value with trailing commas or single quotes; environment variables holding truncated JSON.","solutions":["Fix the JSON syntax of the custom field value named in the error (validate it with a JSON linter or `echo '<value>' | jq .`)","If the value is meant to be a plain string, remove the leading '{' or '[' so it is not treated as JSON","Quote the value properly when setting it via env vars or shell to avoid truncation","Use the error-wrapped key (%s) to locate the exact config entry to fix"],"exampleFix":"// before\n[config.toml]\ncustomfield_10012 = '{\"name\": \"Bug\"'  // missing closing brace\n// after\ncustomfield_10012 = '{\"name\": \"Bug\"}'","handlingStrategy":"validation","validationCode":"for key, val := range cfg.CustomFields {\n\tt := strings.TrimSpace(val)\n\tif (strings.HasPrefix(t, \"{\") || strings.HasPrefix(t, \"[\")) && json.Valid([]byte(t)) == false {\n\t\treturn fmt.Errorf(\"custom field %q is not valid JSON: %q\", key, val)\n\t}\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate config JSON values with jq or json.Valid before loading the tracker","Avoid hand-editing JSON values in config files; use a schema-validated config","Keep plain string values free of leading '{' or '[' unless they are real JSON","Add a config linter step in CI that exercises Init early"],"tags":["config","json","parsing","jira"],"backgroundTag":"invalid-json-config-value","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}