{"record":{"id":"62eb3eb10e0588d7","repo":"gastownhall/beads","slug":"parsing-json-w","errorCode":null,"errorMessage":"parsing JSON: %w","messagePattern":"parsing JSON: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/formula.go","lineNumber":681,"sourceCode":"// formulaToTOML converts a Formula to TOML bytes.\n// Uses a custom structure optimized for TOML readability.\nfunc formulaToTOML(f *formula.Formula) ([]byte, error) {\n\t// We need to re-read the original JSON to get the raw structure\n\t// because the Formula struct loses some ordering/formatting\n\tif f.Source == \"\" {\n\t\treturn nil, fmt.Errorf(\"formula has no source path\")\n\t}\n\n\t// Read the original JSON\n\tjsonData, err := os.ReadFile(f.Source)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"reading source: %w\", err)\n\t}\n\n\t// Parse into a map to preserve structure\n\tvar raw map[string]interface{}\n\tif err := json.Unmarshal(jsonData, &raw); err != nil {\n\t\treturn nil, fmt.Errorf(\"parsing JSON: %w\", err)\n\t}\n\n\t// Fix float64 to int for known integer fields\n\tfixIntegerFields(raw)\n\n\t// Encode to TOML\n\tvar buf bytes.Buffer\n\tencoder := toml.NewEncoder(&buf)\n\tencoder.Indent = \"\"\n\tif err := encoder.Encode(raw); err != nil {\n\t\treturn nil, fmt.Errorf(\"encoding TOML: %w\", err)\n\t}\n\n\t// Post-process to convert escaped \\n in strings to multi-line strings\n\tresult := convertToMultiLineStrings(buf.String())\n\n\treturn []byte(result), nil\n}","sourceCodeStart":663,"sourceCodeEnd":699,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/formula.go#L663-L699","documentation":"After reading the raw formula JSON, formulaToTOML unmarshals it into a generic map to preserve structure. If the file content is not valid JSON, json.Unmarshal fails and the error is wrapped as 'parsing JSON: %w'. This indicates the source file itself is malformed (syntax error, truncation, wrong format), not a conversion logic problem.","triggerScenarios":"Running formula conversion against a source JSON file that is corrupted, truncated (partial write), hand-edited with invalid syntax, or not JSON at all (e.g. already TOML, or an HTML error page saved by mistake).","commonSituations":"Manual edits to formula JSON introducing syntax errors; interrupted writes leaving truncated files; formulas downloaded from a URL where an error page was saved; files converted between formats incorrectly.","solutions":["Validate the JSON: run it through `jq . file.json` or python -m json.tool to find the syntax error at the reported offset.","Fix the JSON syntax (missing comma/brace, trailing comma, single quotes).","Restore the file from git or regenerate it with `bd formula export`/the canonical writer.","Confirm the file is actually JSON, not TOML or HTML; if it's already TOML, no conversion is needed."],"exampleFix":"// before\n{ \"name\": \"deploy\", \"steps\": [ { \"cmd\": \"go test\" } ] }  // trailing content/truncated\n// after\n{\n  \"name\": \"deploy\",\n  \"steps\": [{ \"cmd\": \"go test\" }]\n}","handlingStrategy":"validation","validationCode":"# validate before converting\njq empty .beads/formulas/deploy.json || echo \"invalid JSON\"","typeGuard":null,"tryCatchPattern":"if _, err := formulaToTOML(f); err != nil {\n    var syntaxErr *json.SyntaxError\n    if errors.As(err, &syntaxErr) {\n        // report syntaxErr.Offset to locate the malformed byte\n    }\n}","preventionTips":["Run jq/python json.tool on formula JSON after hand edits.","Never edit formula JSON without re-validating; prefer `bd formula` commands.","Restore corrupted files from git rather than patching blindly.","Ensure downloads are JSON (check Content-Type) before saving as formula sources."],"tags":["formula","json","parsing"],"backgroundTag":"invalid-json","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}