gastownhall/beads · error

json: %w

Error message

json: %w

What it means

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.

Source

Thrown at internal/formula/parser.go:166

	formula.Source = absPath

	// Set source tracing info on all steps (gt-8tmz.18)
	SetSourceInfo(formula)

	p.cache[absPath] = formula

	// Also cache by name for extends resolution
	p.cache[formula.Formula] = formula

	return formula, nil
}

// Parse parses a formula from JSON bytes.
func (p *Parser) Parse(data []byte) (*Formula, error) {
	var formula Formula
	if err := json.Unmarshal(data, &formula); err != nil {
		return nil, fmt.Errorf("json: %w", err)
	}

	// Set defaults
	if formula.Version == 0 {
		formula.Version = 1
	}
	if formula.Type == "" {
		formula.Type = TypeWorkflow
	}

	return &formula, nil
}

// ParseTOML parses a formula from TOML bytes.
func (p *Parser) ParseTOML(data []byte) (*Formula, error) {
	var formula Formula
	if err := toml.Unmarshal(data, &formula); err != nil {
		return nil, fmt.Errorf("toml: %w", err)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the json error's offset/field name and fix that spot in the file.
  2. Run the file through a JSON validator (jq .) to confirm syntax.
  3. Check the extension matches the actual format — a TOML file must use .formula.toml.
  4. Verify field names/types against the current Formula struct for the library version in use.

Example fix

// before (x.formula.json)
{ "formula": "scaffold", "version": "1", } // trailing comma + string version
// after
{ "formula": "scaffold", "version": 1 }
Defensive patterns

Strategy: validation

Validate before calling

if !json.Valid(data) {
	return errors.New("formula bytes are not valid JSON")
}
// optional: strict schema probe
var probe struct {
	Formula string      `json:"formula"`
	Version json.Number `json:"version"`
	Steps   []struct{}  `json:"steps"`
}
if err := json.Unmarshal(data, &probe); err != nil {
	return fmt.Errorf("formula JSON does not match schema: %w", err)
}

Type guard

func isValidFormulaJSON(data []byte) bool {
	var f formula.Formula
	return json.Unmarshal(data, &f) == nil && f.Formula != ""
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/abe41b7564b3b734. Report an issue: GitHub.