{"record":{"id":"abe41b7564b3b734","repo":"gastownhall/beads","slug":"json-w","errorCode":null,"errorMessage":"json: %w","messagePattern":"json: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/formula/parser.go","lineNumber":166,"sourceCode":"\n\tformula.Source = absPath\n\n\t// Set source tracing info on all steps (gt-8tmz.18)\n\tSetSourceInfo(formula)\n\n\tp.cache[absPath] = formula\n\n\t// Also cache by name for extends resolution\n\tp.cache[formula.Formula] = formula\n\n\treturn formula, nil\n}\n\n// Parse parses a formula from JSON bytes.\nfunc (p *Parser) Parse(data []byte) (*Formula, error) {\n\tvar formula Formula\n\tif err := json.Unmarshal(data, &formula); err != nil {\n\t\treturn nil, fmt.Errorf(\"json: %w\", err)\n\t}\n\n\t// Set defaults\n\tif formula.Version == 0 {\n\t\tformula.Version = 1\n\t}\n\tif formula.Type == \"\" {\n\t\tformula.Type = TypeWorkflow\n\t}\n\n\treturn &formula, nil\n}\n\n// ParseTOML parses a formula from TOML bytes.\nfunc (p *Parser) ParseTOML(data []byte) (*Formula, error) {\n\tvar formula Formula\n\tif err := toml.Unmarshal(data, &formula); err != nil {\n\t\treturn nil, fmt.Errorf(\"toml: %w\", err)","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/formula/parser.go#L148-L184","documentation":"Parser.Parse unmarshals raw bytes as JSON into the Formula struct and wraps any json.Unmarshal failure as \"json: ...\". Thrown when the bytes are not syntactically valid JSON or a value's type doesn't match the struct fields. Reached from ParseFile for any file not ending in .formula.toml.","triggerScenarios":"ParseFile called on a *.formula.json (or extension-less) file whose content is invalid JSON or has type mismatches (e.g. version as string, steps as an object instead of array).","commonSituations":"Trailing commas or comments in JSON; file truncated by a failed write; a TOML formula accidentally given a .json extension (ParseFile falls through to JSON parsing for unknown extensions); fields renamed between schema versions.","solutions":["Read the json error's offset/field name and fix that spot in the file.","Run the file through a JSON validator (jq .) to confirm syntax.","Check the extension matches the actual format — a TOML file must use .formula.toml.","Verify field names/types against the current Formula struct for the library version in use."],"exampleFix":"// before (x.formula.json)\n{ \"formula\": \"scaffold\", \"version\": \"1\", } // trailing comma + string version\n// after\n{ \"formula\": \"scaffold\", \"version\": 1 }","handlingStrategy":"validation","validationCode":"if !json.Valid(data) {\n\treturn errors.New(\"formula bytes are not valid JSON\")\n}\n// optional: strict schema probe\nvar probe struct {\n\tFormula string      `json:\"formula\"`\n\tVersion json.Number `json:\"version\"`\n\tSteps   []struct{}  `json:\"steps\"`\n}\nif err := json.Unmarshal(data, &probe); err != nil {\n\treturn fmt.Errorf(\"formula JSON does not match schema: %w\", err)\n}","typeGuard":"func isValidFormulaJSON(data []byte) bool {\n\tvar f formula.Formula\n\treturn json.Unmarshal(data, &f) == nil && f.Formula != \"\"\n}","tryCatchPattern":null,"preventionTips":["Run jq or a JSON linter over .formula.json files before committing.","Never write trailing commas or comments in JSON formula files.","Ensure version is a number and steps/template are arrays."],"tags":["go","json","parse-error","formula"],"backgroundTag":"json-parse-error","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}