gastownhall/beads · error

parse %s: %w

Error message

parse %s: %w

What it means

The formula file was read successfully but failed to parse (JSON or TOML depending on extension); the parse error is wrapped as "parse <path>: ...". This means the file content is not valid for its declared format or doesn't unmarshal into the Formula struct.

Source

Thrown at internal/formula/parser.go:146

		return cached, nil
	}

	// Read and parse the file
	// #nosec G304 -- absPath comes from controlled search paths or explicit user input
	data, err := os.ReadFile(absPath)
	if err != nil {
		return nil, fmt.Errorf("read %s: %w", path, err)
	}

	// Detect format from extension
	var formula *Formula
	if strings.HasSuffix(path, FormulaExtTOML) {
		formula, err = p.ParseTOML(data)
	} else {
		formula, err = p.Parse(data)
	}
	if err != nil {
		return nil, fmt.Errorf("parse %s: %w", path, err)
	}

	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

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the inner parse error's line/column and fix the syntax at that location in the formula file.
  2. Validate the file with a TOML/JSON linter or by running it through the parser in a test.
  3. Ensure field types match the Formula struct (e.g. numeric version, array-of-tables for steps/template).
  4. Restore the file from git if a merge/edit corrupted it.

Example fix

// before (TOML)
formula = "scaffolding
type = "expansion"   # missing closing quote above
// after
formula = "scaffolding"
type = "expansion"
Defensive patterns

Strategy: try-catch

Validate before calling

// syntax-check before handing bytes to the parser
if strings.HasSuffix(path, ".formula.toml") {
	if err := validateTOML(data); err != nil {
		return fmt.Errorf("%s: invalid TOML: %w", path, err)
	}
} else if !json.Valid(data) {
	return fmt.Errorf("%s: invalid JSON", path)
}

Try / catch

f, err := parser.ParseFile(path)
if err != nil {
	if strings.HasPrefix(err.Error(), "parse "+path) {
		return nil, fmt.Errorf("formula file %s is malformed (see wrapped error for line/col)", path)
	}
	return nil, err
}

Prevention

When it happens

Trigger: ParseFile dispatches to ParseTOML for *.formula.toml or Parse otherwise, and the unmarshaler rejects the bytes — syntax errors, wrong types (string where int expected), unknown structures.

Common situations: Hand-edited TOML with a missing quote/bracket; JSON with trailing commas; a `version` field written as a string; merge conflicts left markup in the file; file saved with the wrong extension.

Related errors


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